Множественное наследование Javascript - PullRequest
5 голосов
/ 10 сентября 2011

Может кто-нибудь, пожалуйста, помогите с кодом ниже. Я пытаюсь понять множественное наследование не знаю, почему это не работает. Кстати, если код для множественного наследования. Спасибо

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

    <title>Test Doc</title>
    <script type="text/javascript">
    function classX(){
        this.messageX="this is X Message";
        this.alertX=function(){
            alert(this.messageX);
        };
    }
    function classY(){
        this.messageY="this is Y Message";
        this.alertY=function(){
            alert(this.messageY);
        };
    }
    function classZ(){
        classX.apply(this);
        classY.apply(this);
        this.messageZ="this is Z Message";
        this.alertZ=function(){
            alert(this.messageZ);
        };
    }
    var abjz=new classZ();
    objz.alertZ();
    abjz.alertX();
    </script>
</head>

<body>


</body>
</html>

Ответы [ 7 ]

16 голосов
/ 10 сентября 2011

JavaSript не имеет истинного множественного наследования. Вы можете наследовать только от одного прототипа, а затем скопировать остальные свойства, которые вы хотите. Вы можете проверить это с помощью оператора instanceof.

После исправления неправильного написания ваша демоверсия работает, но на самом деле вы не наследуете по-настоящему. Чтобы сделать истинное наследование JS:

function A(){}
function B(){}
B.prototype = new A;
b = new B;
console.log(b instanceof A, b instanceof B);
//-> true, true

См. Также

Подробнее о JS-наследовании в MDN

Квазимногократное наследование

function ctorX() {
    this.messageX = "this is X Message";
    this.alertX = function() {
        console.log(this.messageX);
    };
}

function ctorY() {
    this.messageY = "this is Y Message";
    this.alertY = function() {
        console.log(this.messageY);
    };
}

function ctorZ() {
    ctorX.call(this); // This is the quasi-multiple inheritance
    this.messageZ = "this is Z Message";
    this.alertZ = function() {
        console.log(this.messageZ);
    };
}
ctorZ.prototype = new ctorY; // This is the actual inheritance

var objz = new ctorZ();
objz.alertZ();
objz.alertY();
objz.alertX();

console.assert(objz instanceof ctorZ, 'objz is not instance of ctorZ');
console.assert(objz instanceof ctorY, 'objz is not instance of ctorY');
console.assert(objz instanceof ctorX, 'objz is not instance of ctorX');
//The last assert will fail since there is no true multiple inheritance

Демонстрация квазимногократного наследования

Избегайте вызова супер-конструктора

HMR поднял вопрос о том, что в некоторых случаях пользователь хочет наследовать от конкретного конструктора, но супер-конструктор требует параметры и потерпит неудачу без них. Способ обойти это - создать прокси-конструктор:

function C(x){if(!x) throw new Error;}
function D(){}
function proxyCtor(){/*should be noop*/}
proxyCtor.prototype = C.prototype;
D.prototype = new proxyCtor;

var d = new D;
console.assert(d instanceof C, 'c is not instance of D');
// will err if incorrect, which it's not

Демо

6 голосов
/ 10 сентября 2011

Вы неправильно написали "abjz" в вызове "alertZ ()".

С этим исправленным, насколько я могу судить, код работает нормально (отображаются два предупреждения, одно для Z и однодля X).

1 голос
/ 11 октября 2016

Вы можете сделать это, создав прокси вокруг прототипов во всех цепочках в дереве множественного наследования (всего дерево ), а затем сгладить это дерево и связать все эти проксифицированные прототипы в DFS предзаказа.ВТП.Затем необходимо обновить [Symbol.hasInstance] для каждого конструктора в дереве наследования, чтобы сказать, что этот конструктор имеет этот экземпляр.Я работаю над этим здесь: https://github.com/dosaygo-coder-0/postjs/blob/master/posttypes/src/mixOf.js

В настоящее время (12 октября 2016 г.) вышеуказанные идеи не полностью реализованы.

1 голос
/ 13 июля 2013

JavaScript не дает доступа к множественному наследованию из коробки.

Чтобы использовать его, вы можете использовать систему классов, которая допускает множественное наследование, например Ring.js .

1 голос
/ 18 июля 2012

Ваш код не вызывает наследования classX и classY классом Z, он просто копирует их свойства / методы.

Object.getOwnPropertyNames(abjz)

показывает: -

messageX,alertX,messageY,alertY,messageZ,alertZ

Но для наследования вы хотите, чтобы методы оповещения оставались только в своих соответствующих классах, чтобы любые изменения в них были отражены в abjz позже. Кроме того, чтобы не возникало проблем с обслуживанием метода, если вы создадите больше экземпляров, таких как abjz.

Вы можете сделать это: -

var classX = {}
classX.messageX = "this is X Message"
classX.alertX = function(){
    alert(this.messageX)
}

var classY = Object.create(classX)
classY.messageY = "this is Y Message"
classY.alertY = function(){
    alert(this.messageY)
}

var classZ = Object.create(classY)
classZ.messageZ = "this is Z Message"
classZ.alertZ = function(){
    alert(this.messageZ)
}

var abjz = Object.create(classZ)

, что эквивалентно: -

function classX(){}
classX.prototype.messageX = "this is X Message"
classX.prototype.alertX = function(){
    alert(this.messageX)
}

function classY(){}
classY.prototype = classX.prototype
classY.prototype.messageY = "this is Y Message"
classY.prototype.alertY = function(){
    alert(this.messageY)
}

function classZ(){}
classZ.prototype = classY.prototype
classZ.prototype.messageZ = "this is Z Message"
classZ.prototype.alertZ = function(){
    alert(this.messageZ)
}

var abjz = new classZ()

Оба должны вывести: -

alert( Object.getOwnPropertyNames(abjz) ) //
abjz.alertX()                             // this is X Message
abjz.alertY()                             // this is Y Message
abjz.alertZ()                             // this is Z Message

Итак, теперь abjz наследует от classZ, который наследует от classY, который наследует от classX в линейной цепочке прототипов, например так: -

abjz --> classZ --> classY --> classX

Это не множественное наследование. Чтобы получить это, abjz должен наследовать напрямую от каждого из classX, classY и classZ без цепочки, т.е.

abjz --> classZ
abjz --> classY
abjz --> classX

К сожалению, система цепочек прототипов JS не позволяет этого, и гибкие преимущества множественного наследования уничтожаются заказанной цепочкой прототипов. Например, если вы также хотите, чтобы экземпляр cdef наследовал только от classZ и classX: -

cdef --> classZ --> classX

тогда в JS прототип classZ должен быть изменен с classY на classX, и это портит экземпляр abjz. В то время как в множественном наследовании: -

cdef --> classZ
cdef --> classX

classZ остаётся безучастным, потому что нет неловкой цепочки, с которой нужно иметь дело.

0 голосов
/ 26 апреля 2018

В книге Beginning Node.js Басарата Сайеда он показывает образец наследования.Этот код демонстрирует его способ настройки цепочки прототипов.Он использует модуль утилит в качестве помощника для связи цепочек прототипов.

На странице 91 «Javascript поддерживает прототипное наследование. Глава 2 его книги объясняет, как работает прототип. В JavaScript выполняется поиск члена текущего элемента (например, item.foo), за которым следуетего прототипом (item. proto .foo), за которым следует прототип прототипа (item. proto . proto .foo), и так досам прототип (например, item. proto . proto . proto ) является нулевым. "- Basarat Syed

Примечание. Редактор переполнения стека лишен префикса "__" и суффикса из прото.

Пример кода.Базовый класс - Animal, класс Bird - из Animal, а класс Superman - из Bird.

var inherits = require('util').inherits;

// Animal class, the parent
function Animal(name){
    this.name = name;

    // Additional initialization code
}

Animal.prototype.walk = function(destination){
    console.log(this.name,'is walking to',destination);
}

Animal.prototype.eat = function(food){
    console.log(this.name,'is eating',food);
}

// Bird class, child of Animal
function Bird(name){
    // call the Animal constructor
    Animal.call(this,name);

    // Additional initialization code
}

Bird.prototype.fly = function(destination){
    console.log(this.name,'is flying to',destination);
}

// Setup the prototype chain from child Bird to parent Animal
inherits(Bird,Animal);

// Superman class, child of Bird
function Superman(name){
    // Call the Bird constructor
    Bird.call(this,name);

    // Additional initialization code
}

Superman.prototype.jump = function(destination){
    console.log(this.name,'jumped over a',destination);
}

// Setup the prototype chain from child Superman to parent Bird
inherits(Superman,Bird);

// Create the parent instance
var animal = new Animal('elephant');
animal.walk('melbourne');
animal.eat('grass');

// Create the child of animal instance
var bird = new Bird('sparrow');
bird.walk('sydney');
bird.fly('melbourne');
bird.eat('seeds');

// Create the child of bird instance
var superman = new Superman('Clark Kent');
superman.fly('Gotham');
superman.walk('Daily planet');
superman.jump('Building');
superman.eat('Hot dogs');

Вывод:

слон идет в Мельбурн
слон ест траву
воробей идет в Сидней
воробей летит в Мельбурн
воробей ест семена
Кларк Кент летит в Готэм
Кларк Кент идет к ежедневной планете
Кларк Кент перепрыгнул через здание
Кларк Кент ест хот-доги

0 голосов
/ 23 июля 2013

Попробуйте эту библиотеку, которая упрощает множественное наследование: https://github.com/meddler/inherit (см .: https://github.com/meddler/inherit/blob/master/test/module/inherit/from.js#L19)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...