如何在JavaScript中创建不能被实例化的抽象基类[英] How to create Abstract base class in JavaScript that can't be Instantiated

本文是小编为大家收集整理的关于如何在JavaScript中创建不能被实例化的抽象基类的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我有一个类

function Node() {
    //implementation
}

和另一个类

function AttributionalNode() {
    this.prototype.setAttr = function (attr) {
        this.atText = attr;
    };
}

AttributionalNode.prototype = new Node();
AttributionalNode.prototype.constructor = AttributionalNode;

如何使class 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(aka es6)类语法的JavaScript引擎中,可以使用new.target meta-property:

来完成此操作.
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 as:

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.lit.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();

本文地址:https://www.itbaoku.cn/post/627797.html

问题描述

I have a class

function Node() {
    //implementation
}

and another class

function AttributionalNode() {
    this.prototype.setAttr = function (attr) {
        this.atText = attr;
    };
}

AttributionalNode.prototype = new Node();
AttributionalNode.prototype.constructor = AttributionalNode;

How to make class Node() so it can't be instantiated? e.g when I try

var node = new Node();

So it throws an Exception?

推荐答案

This would work:

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();

Note: you cannot refer to this.prototype inside the constructor, as the prototype is only a property of the constructor function, not of the instances.

Also, see here for a good article on how to properly extend JS classes.

其他推荐答案

In JavaScript engines that support ECMAScript 2015 (aka ES6) class syntax, this can be accomplished using the new.target meta-property:

function Node() {
   if (new.target === Node) throw TypeError("new of abstract class Node");
}

or using class syntax:

class Node {
   constructor () {
      if (new.target === Node) throw TypeError("new of abstract class Node");
   }
}

in either case, just define AttributionalNode as:

class AttributionalNode extends Node {
   constructor () {
      super();
   }
   setAttr(attr) {
      this.atText = attr;
   }
}

new Node();               // will throw TypeError
new AttributionalNode();  // works fine

For a more detailed explanation of new.target see section 4.2 of this document.

其他推荐答案

Adapting @levi's answer, you can go with a similar solution for using with ES6 today (as new.target isn't established yet):

You can see it running on Babel's 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();