2015-05-31 16 views
25

Ho una classeCome creare classe di base astratta in JavaScript che non può essere un'istanza

function Node() { 
    //implementation 
} 

e un'altra classe

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

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

Come rendere Nodo di classe() in modo che non si può essere istanziato? per esempio quando provo

var node = new Node(); 

Quindi viene generata un'eccezione?

+0

Inserisci 'throw new Exception()' nel costruttore, forse? Non so se questo è valido in Javascript. –

+0

Generalmente non è una buona idea impostare le proprietà del prototipo nella funzione di costruzione. – Pointy

risposta

10

questo dovrebbe funzionare:

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

Nota: non si può fare riferimento alla this.prototype all'interno del costruttore, come il prototipo è solo una proprietà della funzione di costruzione, non delle istanze.

Inoltre, see here per un buon articolo su come estendere correttamente le classi JS.

+0

Si verifica un errore quando una classe tenta di ereditare da Node() –

+2

@AlexandrSargsyan Non lo fa. Ho aggiornato l'esempio per dimostrarlo. – levi

41

In motori JavaScript che supportano ECMAScript 2015 (aka ES6) sintassi di classe, questo può essere realizzato utilizzando il new.target meta-proprietà:

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

o utilizzando la sintassi classe:

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

in entrambe le caso, è sufficiente definire AttributionalNode come:

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

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

Per una spiegazione più dettagliata di new.target vedere la sezione 4.2 di this document.

+1

Puoi fornire un riferimento per 'new.target'? –

+0

new.target non funziona! –

+1

Se si desidera sapere se supporta o no: https://kangax.github.io/compat-table/es6/#new.target. In questo momento, nessun supporto, come affermato. –

5

Adattamento @ risposta di Levi, si può andare con una soluzione simile per l'utilizzo con ES6 oggi (come new.target non è ancora stabilita):

Lo si può vedere in esecuzione su repl di 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(); 
Problemi correlati