クラスがあります
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();
だから、例外をスローしますか?
これはうまくいくでしょう:
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();
注:プロトタイプはインスタンスではなくコンストラクタ関数のプロパティにすぎないため、コンストラクタ内でthis.prototype
を参照することはできません。
また、JSクラスを適切に拡張する方法に関する優れた記事については、 ここを参照 を参照してください。
ECMAScript 2015(別名ES6)クラス構文をサポートするJavaScriptエンジンでは、これは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を参照してください。
@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();
これらのコメントに基づいて、私はこれを書きました
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(", "));
}
}
}
使用法:
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