Вопрос довольно старый, но я создал возможное решение, как создать абстрактный «класс» и заблокировать создание объекта этого типа.
//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();
Как видите, последний объект выдает ошибку, потому что у Animal в прототипе есть свойство abstract
. Чтобы быть уверенным, что это Animal, а не то, что есть Animal.prototype
в цепочке прототипов, я делаю:
Object.getPrototypeOf(this).hasOwnProperty("abstract")
Поэтому я проверяю, что у моего ближайшего объекта-прототипа есть abstract
свойство, только объект, созданный непосредственно из Animal
прототипа, будет иметь это условие на true. Функция hasOwnProperty
проверяет только свойства текущего объекта, а не его прототипы, так что это дает нам 100% уверенность, что свойство объявлено здесь не в цепочке прототипов.
Каждый объект, производный от Object, наследует метод hasOwnProperty . Этот метод можно использовать, чтобы определить, имеет ли объект указанное свойство как прямое свойство этого объекта; в отличие от оператора in, этот метод не проверяет цепочку прототипов объекта. Подробнее об этом:
В моем предложении нам не нужно менять constructor
каждый раз после того, Object.create
как это в текущем лучшем ответе @ Jordão.
Решение также позволяет создавать множество абстрактных классов в иерархии, нам нужно только создать abstract
свойство в прототипе.