LINUX.ORG.RU

Ромбовидное наследование

 ,


0

2

Заинтересовался я тут сабжем

Ромбовидное наследование (англ. diamond inheritance) — ситуация в объектно-ориентированных языках программирования с поддержкой множественного наследования, когда два класса B и C наследуют от A, а класс D наследует от обоих классов B и C. При этой схеме наследования может возникнуть неоднозначность: если метод класса D вызывает метод, определенный в классе A (и этот метод не был переопределен в классе D), а классы B и C по-своему переопределили этот метод, то от какого класса его наследовать: B или C?

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


A=function(){this.x=1}

B=function(){this.a=10; this.x="another_B"}
C=function(){this.b=20; this.x="another_C"}

tmp=new A
B.prototype=tmp
C.prototype=tmp
delete tmp

D=function(){}
tmp=new B
C.call(tmp)
D.prototype=tmp
console.log(tmp) // { a: 10, x: 'another_C', b: 20 }
delete tmp

d=new D

console.log(d.x, d.a, d.b) // another_C 10 20

Тут абсолютно очевидно, что D наследует от C, поскольку мы видим, что в строке C.call(tmp) мы затерли x новым значением.

Таким образом, мы видим, что данная проблема не является проблемой в общем смысле, а это быдло-дизайн-ЯП-специфичная проблема. Просто в некоторых «ЯП» слишком много подковерной возни.



Последнее исправление: anonimous (всего исправлений: 1)

Ответ на: Чем запускать-то? от rogerw

Это жс, но это неважно. Поскольку мы имеем дело с чистым, как слезы младенца, теоретиком, у него любой код помещается в один экран и он даже не представляет, что могут быть ситуации, когда иерархия классов на самом деле сложная, файлов в проекте много, гарантий на порядок линкования нет и т.д.

anonymous
()
Ответ на: комментарий от anonymous

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

anonimous
() автор топика

И почему я забываю проверить автора темы перед её прочтением?

Я, конечно, javascript не знаю, но не увидел тут множественного наследования.

Waterlaz ★★★★★
()

теперь сделай новый класс (назовём его, например, «X») который является одновременно потомком и класса «B» и класса «C».

(подсказка: Javascript не позволяет этого делать :))

user_id_68054 ★★★★★
()

Узнаю автора с первого слова в названии темы

umren ★★★★★
()
Ответ на: комментарий от anonimous

Класс D является таким классом Переименуй D/X, еслит тебе так больше нравится.

нет. :)

спасибо конечно, что вызвал конструктор от «C» для класса «D»:

tmp=new B
C.call(tmp)

но ни где в прототипах «D» — ты не указывал что «D» якобы является потомком от «C» :-)

--------------------------------------------------

с таким же успехом ты вообще мог бы делать ассоциативные массивы {}, вместо объектов (вместо экземпляров JS-классов). и просто вызывать только конструкторы для их инициализации :-)

user_id_68054 ★★★★★
()
Последнее исправление: user_id_68054 (всего исправлений: 2)
Ответ на: комментарий от anonimous

Тебе сахар нужен или ехать?

объекты делать можно и на языке C (без C++)...

...но ведь ни кто не называет язык C объектноориентированным языком. :)

в данном случае ты сымитировал (кое-как) ромбовидное наследование.

а «настоящее» ромбовидное наследование — попросту не возможно в JS.

user_id_68054 ★★★★★
()
Ответ на: комментарий от user_id_68054

Давай, все-таки, отталкиваться от того, что код делает, а не от-того, что там написано.

сымитировал

Это не имитация, а оно и есть.

anonimous
() автор топика
Ответ на: комментарий от anonimous

тык дело в том что — ромбовидное наследование — в реальной жизни не должно случаться.

множественное наследование используют для:

1. интерфейсов.

2. для примесей.

и примеси и интерфейсы — не должны иметь родителей (примеси могут — но безсмысленно вообщем-то).

так что если судить по коду — то нужно очень постараться чтобы допустить негативны эффекты во время ромбовидного наследования :) ..

и твой код — это подтверждает.

в твоём коде — класс «C» играет роль примеси (хоть он и содержит родителя). и как примесь — проблемы он не создаёт.

user_id_68054 ★★★★★
()
Последнее исправление: user_id_68054 (всего исправлений: 1)
Ответ на: комментарий от anonimous

Это не имитация, а оно и есть.

можешь пожалуйста добавить в класс «C» — какой-нибудь метод.

а потом проверить как этот метод открывается из экземпляра «D»

user_id_68054 ★★★★★
()
Ответ на: комментарий от jerk-of-all-trades

возникнуть неоднозначность: если метод

Нет, смысл этой цитаты

возникнуть неоднозначность: если метод

Ключевое слово ЕСЛИ. Тут утверждается, что if (если метод класса D вызывает метод, определенный в классе A (и этот метод не был переопределен в классе D), а классы B и C по-своему переопределили этот метод) неоднозначность=true

Т.е. не в зависимости от ЯП, а в зависимости от этой ситуации. Вот об этом.

anonimous
() автор топика
Ответ на: комментарий от anonimous

Ты идиот.

Проблема в общем случае - это когда она возникает хотя бы в одном.

Kuzy ★★★
()
Ответ на: комментарий от user_id_68054

можешь пожалуйста добавить в класс «C» — какой-нибудь метод. а потом проверить как этот метод открывается из экземпляра «D»

Ты, наверное, код не смотрел. там есть b, который открывается из экземпляра D

anonimous
() автор топика

давай вот такую схему:

есть классы: «A», «B», «C», «D»

«B» наследуется от «A»

«C» наследуется от «A»

«D» наследуется от «B» и «C»

«A» имеет методы (именно методы!) : «x», «y», «z»

«B» переопределяет метод «x»

«C» переопределяет метод «y»

«D» переопределяет метод «z»

user_id_68054 ★★★★★
()
Последнее исправление: user_id_68054 (всего исправлений: 2)
Ответ на: комментарий от anonimous

Ты, наверное, код не смотрел. там есть b, который открывается из экземпляра D

смотрел! (хотя не запускал :))..

b это просто переменная (член класса)

попробуй с методами (а не переменными) — ... вот [эту] схему например

user_id_68054 ★★★★★
()
Ответ на: комментарий от user_id_68054

Зачем я буду голову забивать, скажи конкретно, что это даст в контексте прояснения рассматриваемого вопроса, тогда я мож напишу.

anonimous
() автор топика
Ответ на: комментарий от user_id_68054

попробуй с методами (а не переменными)

Какая нахрен разница


A=function(){this.x=1}

B=function(){this.a=10}
C=function(){this.b=function(){console.log("foo")}}

tmp=new A
B.prototype=tmp
C.prototype=tmp
delete tmp

D=function(){}
tmp=new C
B.call(tmp)
D.prototype=tmp
delete tmp

d=new D
d.b()//foo

anonimous
() автор топика
Ответ на: комментарий от PolarFox

Правильно. Нет множественного наследования — нет проблем

Нет, я к тому, что неоднозначности не возникает при нормальной реализации. А использовать или нет — это уже другой вопрос.

anonimous
() автор топика
Ответ на: комментарий от anonimous

Тогда ты должен указать точно, где именно кривой дизай.

Например вот, представь такой язык:

// A содержит метод foo
class A {
  boo()
  foo()
}

// B наследник A переопределят foo, boo остается старым.
class B : A {
  override foo()
}

// C наследник A переопределят foo, boo остается старым.
class C : A {
  override foo()
}

class D : B, C {
  // какую foo содержит D, B.foo или C.foo?
}

Проблема возникает. Где кривой дизайн? (т.к. я представляю степень твоей упорности, прошу заметить, что язык чисто декларативный и порядок объявления классов не имеет значения)

Kuzy ★★★
()
Ответ на: комментарий от user_id_68054

Все получится. Он запхает методы в конструктор, D наследует от B, а конструктор C он дернет через call. И будет ходить с гордо задратым носом :)

goingUp ★★★★★
()
Ответ на: комментарий от goingUp

Он запхает методы в конструктор

это да.

вот только интересно было бы посмотреть как он это сделал бы если бы дочерний класс — был бы определён в неподконтрольной библиотеке. :)

наверно — отсылал бы bugreport в upstream о том что «переделайте вашу библиотеку, а то у меня проблемы с ромбовидным наследованием!» :)

user_id_68054 ★★★★★
()
Ответ на: комментарий от Kuzy

порядок объявления классов не имеет значения

Вот в этом и кривизна. Т.е. в моем коде, сначала x наследуется от B, а потом затирается значением, от С. Получается, что либо мы абстрагируемся от порядка вычислений, и довольствуемся кривизной, либо выбрасываем нахрен это фапе-говно, и берем нормальный ЯП.

anonimous
() автор топика
Ответ на: комментарий от anonimous

Я в данном случае засунул в класс-предок, как ты и просил.

ты не в класс предок засунул! а в экземпляр

засунь в класс!

user_id_68054 ★★★★★
()
Ответ на: комментарий от user_id_68054

засунь в класс!

Так чтоле?


A=function(){this.x=function(){console.log("foo")}}

B=function(){this.a=10}
C=function(){this.b=function(){console.log("foo")}}

tmp=new A
B.prototype=tmp
C.prototype=tmp
delete tmp

D=function(){}
tmp=new C
B.call(tmp)
D.prototype=tmp
delete tmp

d=new D
d.x()//foo

anonimous
() автор топика
Ответ на: комментарий от anonimous

нее...

ща, погодь,... внесу правки:

:-)

это

A=function(){this.x=function(){console.log("foo")}}
заменить на
A.prototype.x = function(){console.log("foo")}

и

это

C=function(){this.b=function(){console.log("foo")}}
заменить на
C.prototype.b = function(){console.log("foo")}

ну и так далее

вобщем ты должен понять уже думаю... :)

# P.S.: весь код целиком я не написал — так как всё равно он не заработает :)

user_id_68054 ★★★★★
()
Ответ на: комментарий от anonimous

Ясно. То есть ты считаешь что статическое ООП не Ъ и приводишь пример - проблему ромба.

Теперь посмотри что ты написал в ОП-посте.

Таким образом, мы видим, что данная проблема не является проблемой в общем смысле.

Является. ООП бывает статическое и динамическое, бывает вообще без множественного наследования, в статическом ООП с множественным наследованием эта проблема возникает.

Это разные случаи (статическое ООП, динамическое ...) ООП. В нескольких из них существует проблема ромба. Значит она существует для ООП (общего случая).

Kuzy ★★★
()
Ответ на: комментарий от user_id_68054

Я чет непонел. Я даю тебе то, что ты просил. А ты мне говоришь: не, напиши мне кривой неработающий код, чтобы я доказал тебе, что ничо не работает. Ну-ну...

anonimous
() автор топика
Ответ на: комментарий от Kuzy

Значит она существует для ООП (общего случая).

Не, у тебя с логикой что-то. Статическая реализация ООП — это частный случай реализации. Не работает в частном случае (который ты указал — совершенно справедливо)

anonimous
() автор топика
Ответ на: комментарий от anonimous

А ты мне говоришь: не, напиши мне кривой неработающий код, чтобы я доказал тебе, что ничо не работае

ты всё перепутал. всё не так :-)

кривой код — это тот код, который содержит изобилие хаков.

а я прошу у тебя убрать хаки (сделать код не кривым) и ,забегая вперёд я предсказываю subject не заработает.

user_id_68054 ★★★★★
()
Ответ на: комментарий от anonimous

Там нет хаков

кроме той ситуации что ты присваиваешь методы экземплярам :) , вместо декларирования методов на уровне классов.

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

но в данном случае — программируя на JS — так не поступают хорошие ребята.

потому что в твоём хаке — чем больше методов будет у экземпляра — тем дольше он будет иниицализироваться (а этого не должно происходить. скорость инициализирования экземпляра НЕ должна зависить от количества методов этого экземпляра)

user_id_68054 ★★★★★
()
Последнее исправление: user_id_68054 (всего исправлений: 3)
Ответ на: комментарий от anonimous

Не, у тебя с логикой что-то

Лол.

Давай по другому.

В ООП, в общем случаи, существует проблема ромба, в некоторых частных случаях (прототипное ООП, без множественно наследываение) нет.

Норм игра слов?

Kuzy ★★★
()
Ответ на: комментарий от user_id_68054

так не поступают хорошие ребята.

Это все дешевый пиар недоумков, вроде крокфорда. На самом деле, все, что он там идентифицировал как «сильные стороны», «best practice» — это лишь бледная тень настояшей силы js. Настоящая сила — в смолток/селф корнях. Да, так работает прототипное ООП. Никаких хаков. Что там пишут миллион хомячков, не меняет сути языка.

anonimous
() автор топика
Ответ на: комментарий от Kuzy

да..

и с учётом данной темы я должен поправить :-)

В ООП, в общем случаи, существует проблема ромба, в некоторых частных случаях (прототипное ООП, без множественно наследываение, использование хаков вместо стандартного ООП) нет.

fixed

user_id_68054 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.