1.0.4 • Published 6 years ago

@kingjs/interface v1.0.4

Weekly downloads
-
License
MIT
Repository
-
Last release
6 years ago

@kingjs/interface

A repository of functions where every function passed to defineImplementation has assigned to its prototype every function that's passed to defineExtension, and vice-versa.

Usage

Implement any(), none(), ReadOnlyList, and Queue separately, and use an interface to attach the algorithms to the containers like this:

// containers
function ReadOnlyList(array) {
  this.count = function () { return array.length; }
  this.get = function (i) { return array[i]; }
}
function Queue() {
  var array = [];
  this.count = function () { return array.length; }
  this.push = function (x) { array.push(x); }
  this.pop = function () { return array.unshift(); }
}

// algorithms
function any() {
  return this.count() > 0;
}
function none() {
  return this.count() == 0;
}

// interface
var Interface = require('@kingjs/interface');
var interface = new Interface();
interface.registerImplementations([ ReadOnlyList, Queue ]);
interface.registerExtensions({ 
  any: any,
  none: none
});

// tests
var testList = new ReadOnlyList([1, 2, 3]);
var testQueue = new Queue();

var actual = {
  testList: {
    any: testList.any(),
    none: testList.none()
  },
  testQueue: { 
    any: testQueue.any(),
    none: testQueue.none()
  }
};

outputs:

{
  testList: {
    any: true,
    none: false
  },
  testQueue: { 
    any: false,
    none: true
  }
};

Modules

Separate the module containing the containers, from the module containing the algorithms, from the interface that joins them together, like this:

iCountable.js

var Interface = require('@kingjs/interface');

var iCountable = new Interface();

module.exports = iCountable;

> containers.js
```js
function ReadOnlyList(array) {
  this.count = function () { return array.length; }
  this.get = function (i) { return array[i]; }
}
function Queue() {
  var array = [];
  this.count = function () { return array.length; }
  this.push = function (x) { array.push(x); }
  this.pop = function () { return array.unshift(); }
}

var interface = require('./iCountable.js');
interface.registerImplementations([ ReadOnlyList, Queue ]);

exports.ReadOnlyList = ReadOnlyList;
exports.Queue = Queue;

algorithms.js

function any() {
  return this.count() > 0;
}
function none() {
  return this.count() == 0;
}

var interface = require('./iCountable.js'); interface.registerExtensions({ any: any, none: none });

> client.js

```js
require('./algorithms.js');
var Containers = require('./containers.js');
var ReadOnlyList = Containers.ReadOnlyList;
var Queue = Containers.Queue;

var testList = new ReadOnlyList([1, 2, 3]);
var testQueue = new Queue();

var actual = {
  testList: {
    any: testList.any(),
    none: testList.none()
  },
  testQueue: { 
    any: testQueue.any(),
    none: testQueue.none()
  }
};

API

declare class Interface {

  constructor(bases?: Interface[]);

  defineExtension(
    name: string, extension: Function
  ): Function;

  registerExtensions(
    extensions: { [index: string]: Function }
  );

  defineImplementation(
    implementation: Function
  ): Function;

  registerImplementations(
    implementations: Function[]
  ): void;

  bases(): IEnumerable<Interface>;

  implementations(): IEnumerable<Function>;
  
  extensions(): IEnumerable<{
    name: string,
    func: Function
  }>;
}

interface IEnumerable<T> {
  getEnumerator(): {
    moveNext(): { Boolean },
    current: T
  }
}

Methods

constructor: A repository of functions where every function passed to defineImplementation has assigned to its prototype every function that's passed to defineExtension, and vice-versa.

defineExtension: Attaches an extension to the prototype of functions previously passed to registerImplementations. Retains the extension for assignment to subsequent implementations.

registerExtensions: Batch registers extensions.

registerImplementations: Calls itself on any base interfaces. Assigns name/function pairs previously passed to registerExtensions to the implementation prototype. Retains the implementations for future extension.

defineImplementation: Batch registers implementations.

bases: Base interfaces.

implementations: Retained implementations.

extensions: Retained extensions.

Remarks

Extension names occupy a global namespace. To prevent collisions, each developer should affix a unique prefix to their algorithm names. For example, I plan on implementing the LINQ suite of algorithms and will prefix them all with Linq. This way, LinqAny will not conflict with Joe's implementation which he'll name JoesAny.

Install

With npm installed, run

$ npm install @kingjs/interface

Acknowledgments

Interface was inspired by C# extension methods.

See Also

License

MIT

1.0.4

6 years ago

1.0.3

6 years ago

1.0.2

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago