Как создать абстрактный базовый класс в JavaScript, который не может быть создан
У меня есть класс
function Node() {
//implementation
}
и еще один класс
function AttributionalNode() {
this.prototype.setAttr = function (attr) {
this.atText = attr;
};
}
AttributionalNode.prototype = new Node();
AttributionalNode.prototype.constructor = AttributionalNode;
Как создать класс Node(), чтобы он не мог быть создан?
например, когда я пытаюсь
var node = new Node();
Итак, он выбрасывает исключение?
Ответы
Ответ 1
Это будет работать:
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();
Ответ 2
В механизмах JavaScript, поддерживающих синтаксис класса ECMAScript 2015 (иначе ES6), это можно выполнить с помощью мета-свойства new.target
:
function Node() {
if (new.target === Node) throw TypeError("new of abstract class Node");
}
или используя синтаксис класса:
class Node {
constructor () {
if (new.target === Node) throw TypeError("new of abstract class Node");
}
}
в любом случае, просто определите AttributionalNode
как:
class AttributionalNode extends Node {
constructor () {
super();
}
setAttr(attr) {
this.atText = attr;
}
}
new Node(); // will throw TypeError
new AttributionalNode(); // works fine
Более подробное объяснение new.target
см. раздел 4.2 этого документа.
Ответ 3
Адаптируя ответ @levi, вы можете пойти с аналогичным решением для использования с ES6 сегодня (поскольку new.target
еще не установлен):
Вы можете увидеть, как он работает на Babel repl: 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();