J'ai un cours
function Node() {
//implementation
}
et une autre classe
function AttributionalNode() {
this.prototype.setAttr = function (attr) {
this.atText = attr;
};
}
AttributionalNode.prototype = new Node();
AttributionalNode.prototype.constructor = AttributionalNode;
Comment créer la classe Node () pour qu'elle ne puisse pas être instanciée? par exemple quand j'essaye
var node = new Node();
Donc, cela lève une exception?
Cela fonctionnerait:
function Node() {
if (this.constructor === Node) {
throw new Error("Cannot instantiate this class");
}
}
function AttributionalNode() {
Node.call(this); // call super
}
AttributionalNode.prototype = Object.create(Node.prototype);
AttributionalNode.prototype.setAttr = function (attr) {
this.atText = attr;
};
AttributionalNode.prototype.constructor = AttributionalNode;
var attrNode = new AttributionalNode();
console.log(attrNode);
new Node();
Remarque: vous ne pouvez pas vous référer à this.prototype
à l'intérieur du constructeur, car le prototype n'est qu'une propriété de la fonction constructeur, pas des instances.
Aussi, voir ici pour un bon article sur la façon d'étendre correctement les classes JS.
Dans les moteurs JavaScript qui prennent en charge la syntaxe de classe ECMAScript 2015 (aka ES6), cela peut être accompli en utilisant le new.target
méta-propriété:
function Node() {
if (new.target === Node) throw TypeError("new of abstract class Node");
}
ou en utilisant la syntaxe de classe:
class Node {
constructor () {
if (new.target === Node) throw TypeError("new of abstract class Node");
}
}
dans les deux cas, définissez simplement AttributionalNode
comme:
class AttributionalNode extends Node {
constructor () {
super();
}
setAttr(attr) {
this.atText = attr;
}
}
new Node(); // will throw TypeError
new AttributionalNode(); // works fine
Pour une explication plus détaillée de new.target
voir la section 4.2 de ce document .
En adaptant la réponse de @ levi, vous pouvez opter pour une solution similaire à utiliser avec ES6 aujourd'hui (comme new.target
n'est pas encore établi):
Vous pouvez le voir fonctionner sur la réplique de Babel: http://bit.ly/1cxYGOP
class Node {
constructor () {
if (this.constructor === Node)
throw new Error("Cannot instantiate Base Class");
}
callMeBaby () {
console.log("Hello Baby!");
}
}
class AttributionalNode extends Node {
constructor () {
super();
console.log("AttributionalNode instantiated!");
}
}
let attrNode = new AttributionalNode();
attrNode.callMeBaby();
let node = new Node();
Sur la base de ces commentaires, j'ai écrit ceci
class AbstractClass {
constructor() {
if(new.target === AbstractClass || this.__proto__.__proto__.constructor === AbstractClass)
throw new TypeError("Cannot construct "+ this.constructor.name + " class instances directly");
let exceptions = {};
let currProto = this;
while(currProto.constructor !== AbstractClass ) {
for(let method of (currProto.constructor.abstractMethods || [])) {
if("function" !== typeof(this[method]))
exceptions[method] = currProto.constructor.name;
}
currProto = currProto.__proto__;
}
if(0 !== Object.keys(exceptions).length) {
let exceptionsArray = [];
for(let method in exceptions) {
exceptionsArray.Push( exceptions[method] + "." + method);
}
exceptionsArray.sort();
throw new TypeError("Must override the following methods: " + exceptionsArray.join(", "));
}
}
}
Usage:
class MyAbstractClass1 extends AbstractClass {
static abstractMethods = [
"myMethod1", // (x:string, y:string): string
"myMethod2" // (y:string, z:string): string
]
}
class MyAbstractClass2 extends MyAbstractClass1 {
static abstractMethods = [
"myMethod3", // (x:string, y:string): string
"myMethod4" // (y:string, z:string): string
]
}
class MyClass extends MyAbstractClass2 {
myMethod1(x, y){return "Apple"}
}
new MyClass()
//Error