Pytanie jest dość stare, ale stworzyłem możliwe rozwiązanie, jak stworzyć abstrakcyjną „klasę” i blokować tworzenie obiektów tego typu.
//our Abstract class
var Animal=function(){
this.name="Animal";
this.fullname=this.name;
//check if we have abstract paramater in prototype
if (Object.getPrototypeOf(this).hasOwnProperty("abstract")){
throw new Error("Can't instantiate abstract class!");
}
};
//very important - Animal prototype has property abstract
Animal.prototype.abstract=true;
Animal.prototype.hello=function(){
console.log("Hello from "+this.name);
};
Animal.prototype.fullHello=function(){
console.log("Hello from "+this.fullname);
};
//first inheritans
var Cat=function(){
Animal.call(this);//run constructor of animal
this.name="Cat";
this.fullname=this.fullname+" - "+this.name;
};
Cat.prototype=Object.create(Animal.prototype);
//second inheritans
var Tiger=function(){
Cat.call(this);//run constructor of animal
this.name="Tiger";
this.fullname=this.fullname+" - "+this.name;
};
Tiger.prototype=Object.create(Cat.prototype);
//cat can be used
console.log("WE CREATE CAT:");
var cat=new Cat();
cat.hello();
cat.fullHello();
//tiger can be used
console.log("WE CREATE TIGER:");
var tiger=new Tiger();
tiger.hello();
tiger.fullHello();
console.log("WE CREATE ANIMAL ( IT IS ABSTRACT ):");
//animal is abstract, cannot be used - see error in console
var animal=new Animal();
animal=animal.fullHello();
Jak widać ostatni obiekt daje nam błąd, to dlatego, że Animal w prototypie ma własność abstract
. Aby mieć pewność, że jest to Animal, a nie coś, co ma Animal.prototype
w łańcuchu prototypów, robię:
Object.getPrototypeOf(this).hasOwnProperty("abstract")
Więc sprawdzam, czy mój najbliższy obiekt prototypowy ma abstract
właściwość, tylko obiekt utworzony bezpośrednio z Animal
prototypu będzie miał ten warunek na true. Funkcja hasOwnProperty
sprawdza tylko właściwości aktualnego obiektu, a nie jego prototypów, więc daje nam to 100% pewności, że właściwość jest zadeklarowana tutaj, a nie w łańcuchu prototypów.
Każdy obiekt pochodzący z Object dziedziczy metodę hasOwnProperty . Ta metoda może służyć do określenia, czy obiekt ma określoną właściwość jako bezpośrednią właściwość tego obiektu; w przeciwieństwie do operatora in, ta metoda nie sprawdza łańcucha prototypów obiektu. Więcej na ten temat:
W mojej propozycji nie musimy zmieniać za constructor
każdym razem, Object.create
jak to jest w aktualnej najlepszej odpowiedzi @ Jordão.
Rozwiązanie umożliwia również tworzenie wielu abstrakcyjnych klas w hierarchii, wystarczy stworzyć abstract
własność w prototypie.