Skip to content

Instantly share code, notes, and snippets.

@grindfuk
Created April 27, 2016 16:45
Show Gist options
  • Save grindfuk/2c5b4fd546f178fe8fe039346284164b to your computer and use it in GitHub Desktop.
Save grindfuk/2c5b4fd546f178fe8fe039346284164b to your computer and use it in GitHub Desktop.
Node.js ES6 Class Interface
'use strict';
class NotImplementedException extends Error {
}
class InvalidInitialization extends Error {
}
function abc(cls, options) {
let iname = options ? options.interfaceName : 'Interface';
let metaData = {
child: null,
interfaceCls: {
name: iname,
required: []
}
};
let child = cls;
let instance = [];
let properties;
metaData.child = child.constructor.name;
do {
properties = Object.getOwnPropertyNames(child);
if (Object.getPrototypeOf(child).constructor.name === iname) {
metaData.interfaceCls.name = child.constructor.name;
if (cls.constructor.name === child.constructor.name) {
throw new InvalidInitialization(
`Abstract Interface ${metaData.child} cannot be initialized`);
}
let mismatch = [];
for (let key in properties) {
if (properties[key] !== 'constructor') {
metaData.interfaceCls.required.push(properties[key]);
if (instance.indexOf(properties[key]) < 0) {
mismatch.push(properties[key]);
}
}
}
if (mismatch.length > 0) {
throw new NotImplementedException(
`Interface Instance ${metaData.child} does not implement: ${mismatch}`);
}
break;
} else {
for (let key in properties) {
if (properties[key] !== 'constructor') {
instance.push(properties[key]);
}
}
}
child = Object.getPrototypeOf(child);
} while (child);
return metaData;
}
class Interface {
constructor () {
this.imeta = abc(this);
}
}
module.exports = Interface;
if (require.main === module) {
// Interface = require('interface.js');
// 1. Set up your Interface here
class IAnimal extends Interface {
says() {
/* I'm supposed to do this */
}
}
// 2. Make all your children
class Cat extends IAnimal {
constructor () {
super();
}
says() {
console.log('Im a cat');
}
}
class BadCat extends IAnimal {
}
class BadCatChild extends BadCat {
}
// 3. Check your children
let felix = new Cat();
felix.says();
// >> Im a cat
try {
let garfield = new BadCat();
} catch (e) {
console.log(e.message);
// >> Interface Instance BadCat does not implement: says
}
try {
let garfieldsKid = new BadCatChild();
} catch (e) {
console.log(e.message);
// >> Interface Instance BadCatChild does not implement: says
}
try {
let newInterface = new IAnimal();
} catch (e) {
console.log(e.message);
// >> Abstract Interface IAnimal cannot be initialized
}
}
@ygmpkk
Copy link

ygmpkk commented Jul 4, 2018

it is implement Python ABC interface?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment