Created
April 27, 2016 16:45
-
-
Save grindfuk/2c5b4fd546f178fe8fe039346284164b to your computer and use it in GitHub Desktop.
Node.js ES6 Class Interface
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
it is implement Python ABC interface?