-
Notifications
You must be signed in to change notification settings - Fork 1
Class multiinh
Зачем нужно множественное наследование в JS? Затем же, зачем и в других языках.
Один из распространённых случаев: когда классам из различных ветвей иерархии приходится выполнять сходные действия.
В качестве примеров классов для множественного наследования, можно рассмотреть классы из модуля go.Ext.
Нужно передать в go.Class
аргументом не родительский класс, а массив родительских классов.
var OneClass = go.Class({ /* ... */ }),
TwoClass = go.Class({ /* ... */ }),
ThreeClass = go.Class({ /* ... */ }),
ChildClass = go.Class([OneClass, TwoClass, ThreeClass], {
// ...
});
В примере ChildClass
наследуется сразу от 3-х классов.
При наличии одноимённых методов в нескольких родительских классах, в дочерний класс попадает метод из класса объявленного в списке раньше других.
Так как JavaScript не позволяет создавать множественное наследование через прототипы, то здесь происходит следующее:
- Класс, указанный первым, является "основным" предком. Он используется для наследования через цепочку прототипов.
- Остальные классы из списка являются "дополнительными". Их свойства и методы просто копируются в прототип дочернего класса (если там ещё нет одноимённых).
Таким образом, с теоретической точки зрения, за место класса в иерархии отвечает основной предок, а дополнительные являются скорее примесями. При этом если идеологически все предки являются примесями, то основной класс можно не указывать:
ChildClass = go.Class([null, OneClass, TwoClass, ThreeClass], {
// ...
});
В этом случае основным будет базовый класс go.Class.Root
.
Так как дополнительные классы предназначены только для копирования из них свойств и методов, то в их качестве можно использовать не только классы порождённые через go.Class
, но и простые объекты или функции-конструкторы (будет использован их прототип):
var methods = {
'method' : function () {
return "method";
}
};
var ChildClass = go.Class([ParentClass, methods], {});
Так как дополнительные классы не попадают в цепочки прототипов дочернего, то instanceof
для них не работает.
var instance = ChildClass();
instance instanceof ChildClass; // true
instance instanceof OneClass; // true
instance instanceof TwoClass; // false
instance instanceof ThreeClass; // false
Следует использовать метод instance_of()
:
var instance = ChildClass();
instance.instance_of(ChildClass); // true
instance.instance_of(OneClass); // true
instance.instance_of(TwoClass); // true
instance.instance_of(ThreeClass); // true
Для классов же isSubclassOf()
:
ChildClass.isSubclassOf(OneClass); // true
ChildClass.isSubclassOf(TwoClass); // true
ChildClass.isSubclassOf(ThreeClass); // true
ThreeClass.isSubclassOf(ChildClass); // false