@kingjs/reflect.implement-interface

1.0.2 • Public • Published

@kingjs/reflect.implement-interface

Extends kingjs/reflect.define-property to map names to symbols according to iface.

Usage

var assert = require('assert')
var defineInterface = require('@kingjs/define-interface');
var implementInterface = require('@kingjs/reflect.implement-interface');

var InterfaceId = Symbol.for('@kingjs/IInterface.id');

// Demonstrate interoperating with existing interfaces like this:
// `Symbol.iterator` can be thought of as an interface with a single 
// method whose symbolic id is the same as the symbolic id of the 
// interface itself.
var kingjs = { };
var { IIterable } = defineInterface(
  kingjs, 'IIterable', {
    id: Symbol.iterator,
    members: {
      getIterator: Symbol.iterator
    }
  }
);

assert(IIterable.getIterator == Symbol.iterator);
assert(IIterable.GetIterator == Symbol.iterator);
assert(IIterable[InterfaceId] == IIterable.getIterator);

// now, any instance that's Symbol.iterator now implements IIterable!
assert(new Array() instanceof IIterable);
assert(new Map() instanceof IIterable);
assert(new Set() instanceof IIterable);

var instance = { foo: 0 };
implementInterface(instance, IIterable, {
  methods: {
    getIterator: function* () {
      for (var name in this)
        yield { name, value: this[name] };
    }
  }
});

var { GetIterator } = IIterable;
var iterator = instance[GetIterator]();
var next = iterator.next();
assert(!next.done);
assert.deepEqual(next.value, { name: 'foo', value: 0 });
next = iterator.next();
assert(next.done);

// Demonstrate a multi property interfaces like this:
// `IEnumerable` has a single method `getEnumerator` that returns an
// `IEnumerable` that has a property `current` and a method `moveNext`
// which returns `true` if there are more elements or `false` if not.
var { IEnumerable } = defineInterface(
  kingjs, 'IEnumerable', {
    id: '@kingjs/interface.IEnumerable',
    members: {
      getEnumerator: null
    }
  }
);

assert(IEnumerable[InterfaceId] == Symbol.for('@kingjs/interface.IEnumerable'))
assert(IEnumerable.getEnumerator == Symbol.for('@kingjs/interface.IEnumerable.getEnumerator'))
assert(IEnumerable.GetEnumerator == Symbol.for('@kingjs/interface.IEnumerable.getEnumerator'))

var { IEnumerator } = defineInterface(
  kingjs, 'IEnumerator', {
    id: '@kingjs/interface.IEnumerator',
    members: {
      current: null,
      moveNext: null,
    }
  }
);

assert(IEnumerator[InterfaceId] == Symbol.for('@kingjs/interface.IEnumerator'))
assert(IEnumerator.current == Symbol.for('@kingjs/interface.IEnumerator.current'))
assert(IEnumerator.Current == Symbol.for('@kingjs/interface.IEnumerator.current'))
assert(IEnumerator.moveNext == Symbol.for('@kingjs/interface.IEnumerator.moveNext'))
assert(IEnumerator.MoveNext == Symbol.for('@kingjs/interface.IEnumerator.moveNext'))

var instance = [ 1 ];
implementInterface(instance, IEnumerable, {
  methods: {
    getEnumerator: function() {
      var target = this;
      var index = -1;

      return implementInterface({ }, IEnumerator, {
        methods: {
          moveNext: () => ++index < target.length
        },
        accessors: {
          current: () => target[index]
        }
      });
    }
  }
});

var enumerator = instance[IEnumerable.GetEnumerator]();
assert(enumerator[IEnumerator.MoveNext]());
assert(enumerator[IEnumerator.Current] == 1);
assert(!enumerator[IEnumerator.MoveNext]());

// demonstrate "The Diamond" where IB is indirectly inherited twice.
// IA : IX, IY
// IX : IB
// IY : IB
var { IB } = defineInterface(kingjs, "IB", {
  id: '@kingjs/interface.IB',
  members: { foo: null }
});

var { IX } = defineInterface(kingjs, "IX", {
  id: '@kingjs/interface.IX',
  members: { foo: null },
  extends: [ IB ]
})

var { IY } = defineInterface(kingjs, "IY", {
  id: '@kingjs/interface.IY',
  members: { foo: null },
  extends: [ IB ]
})

var { IA } = defineInterface(kingjs, "IA", {
  id: '@kingjs/interface.IA',
  members: { foo: null },
  extends: [ IX, IY ]
})

var instance = { };

// implement IB
implementInterface(instance, IB, {
  methods: { foo: () => null }
});

// implement IX
implementInterface(instance, IX, {
  methods: { foo: () => null }
});

// cannot implement IA without first implementing IY 
assert.throws(() => 
  implementInterface(instance, IA, {
    methods: { foo: () => null }
  })
)
implementInterface(instance, IY, {
  methods: { foo: () => null }
});

// cannot implement IA without also providing IA.foo
assert.throws(() => 
  implementInterface(instance, IA, { })
)

// implement IA
implementInterface(instance, IA, {
  methods: { foo: () => null }
});

API

implementInterface(target, iface, descriptors)

Parameters

  • target: The target on which the interface will be declared.
  • iface: A map for names to symbols used to rename properties declared in the descriptor.
  • descriptors: A descriptor of methods and accessors that implement the interface.
  • descriptors.accessors: Descriptors that implement the interfaces' accessors.
  • descriptors.methods: Descriptors that implement the interfaces' methods.

Returns

Returns target.

Install

With npm installed, run

$ npm install @kingjs/reflect.implement-interface

Dependencies

Package Version
@kingjs/is ^1.0.9
@kingjs/reflect.define-accessor ^1.0.1
@kingjs/reflect.define-function ^1.0.1

Source

https://repository.kingjs.net/reflect/implement-interface

License

MIT

Analytics

Readme

Keywords

none

Package Sidebar

Install

npm i @kingjs/reflect.implement-interface

Weekly Downloads

1

Version

1.0.2

License

MIT

Unpacked Size

10.2 kB

Total Files

5

Last publish

Collaborators

  • kingces95