Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2004.08.29;
Скачать: [xml.tar.bz2];

Вниз

Множественное наследование: почему его нет?   Найти похожие ветки 

 
KSergey ©   (2004-08-10 12:48) [0]

А вот мой коллега задался иным вопросом: а почему в дельфи нет мнжественного наследования? Это лишь религия, или здесь есть более глубинные смыслы (читай: принципиальные технические ограничения) в построении виртуальной таблицы/распределении памяти/однопроходности компиляции и п.т.?


 
имя   (2004-08-10 12:57) [1]

Удалено модератором


 
jack128 ©   (2004-08-10 13:09) [2]


> НЕутУТь_НикАСперли  
ну ведь на плюсах конфликты имен как то решаются ;-)


 
Думкин ©   (2004-08-10 13:10) [3]

> как то решаются


 
имя   (2004-08-10 13:12) [4]

Удалено модератором


 
Ega23 ©   (2004-08-10 13:13) [5]

Если честно, пока ещё не сталкивался с практической задачей, где самым изящным решением было бы множественное наследование.


 
Mihey_temporary ©   (2004-08-10 13:17) [6]



TMyClass1 = class
procedure do();
end;

TMyClass2 = class
procedure do();
end;

TMyClass3 = class(TMyClass1,TMyClass2)
procedure DoSomeThing();
end;

.....
procedure TMyClass3.DoSomeThing();
begin
do(); <----- кто виноват? что делать? едят ли курицу руками?
end;



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


 
Игорь Шевченко ©   (2004-08-10 13:19) [7]

Mihey_temporary ©   (10.08.04 13:17) [6]

А зачем смешивать классы с одинаковыми методами ?


 
ламер ©   (2004-08-10 13:19) [8]

> Ega23 ©   (10.08.04 13:13) [5]
честно говоря, я пока ещё вообще не встречал задач, в которых требовалось бы множественное наследование. :) всегда хватает интерфейсов.


 
Mihey_temporary ©   (2004-08-10 13:20) [9]

>А зачем смешивать классы с одинаковыми методами ?

Одинаковое название, но не сама реализация.


 
Anatoly Podgoretsky ©   (2004-08-10 13:29) [10]

Игорь Шевченко ©   (10.08.04 13:19) [7]
Это не принципиально и в рамках ООП


 
kirasuki ©   (2004-08-10 13:45) [11]

Опять же ничего не буду говорить о месте множественного наследования в ООП, у него есть свои недостатки и приемущества. Однако если посмотреть MFC hierachy chart (MSDN), то вы найдете там пару классов, имеющих двух предков.
А методы базовых классов, имеющие одинаковые имена в C++ вызываются примерно так:

class A {
public:
 void do() {}
};

class B {
public:
 void do {}
};

class C: public A, public B {};

C c;

с.A::do() // метод родителя A
с.B::do() // метод родителя B


 
kirasuki ©   (2004-08-10 13:47) [12]

Простите за очепятки, меня несчастного.

class A {
public:
void do() {}
};

class B {
public:
void do() {}
};

class C: public A, public B {};

C c;

с.A::do(); // метод родителя A
с.B::do(); // метод родителя B


 
Игорь Шевченко ©   (2004-08-10 13:47) [13]

kirasuki ©   (10.08.04 13:45) [11]


> А методы базовых классов, имеющие одинаковые имена в C++
> вызываются примерно так:


Да я вообще-то не об этом, а зачем смешивать их, создавая себе лишние проблемы ?


 
kirasuki ©   (2004-08-10 13:49) [14]

Это может не зависеть от программиста, которому достался код с плохой "наследственностью".


 
DiamondShark ©   (2004-08-10 13:57) [15]


> Да я вообще-то не об этом, а зачем смешивать их, создавая
> себе лишние проблемы ?

Да незачем. Просто может так оказаться, что вот захотелось создать множественного наследника, а в предках -- бац! -- одинаковые методы.

Кстати, как эта ситуация в Ц++ обрабатывается? Компилируется или ругается?


 
icWasya ©   (2004-08-10 15:14) [16]

Для чего нужно - ну например посмотрите на закладку компонент DataControls. И посмотрите на реализацию этих компонент. В каждом компоненте есть код доступа к полю таблицы. Но TDBLabel наследуется от TCustomLabel, TDBEdit от TCustomEdit и.т.д. И у них НЕТ общего предка типа TFieldLink! И если пишется компонент типа TDBCtrlGrid, которому нужно знать - является ли компонент DataAware, то узнаётся это не через механизм наследования, as-is , а через сообщения, причём код обработки этого сообщения (CM_GETDATALINK) во всех компонентах абсолютно одинаковый

procedure TDB_xxx.CMGetDataLink(var Message: TMessage);
begin
 Message.Result := Integer(FDataLink);
end;

бери и делай общего предка, но....
ИМХО


 
Игорь Шевченко ©   (2004-08-10 15:50) [17]

DiamondShark ©   (10.08.04 13:57) [15]


> Кстати, как эта ситуация в Ц++ обрабатывается? Компилируется
> или ругается?


Ругается:
myprojects\testinheritance\testinheritance.cpp(23) : error:  "C::Do" is ambiguous
myprojects\testinheritance\testinheritance.cpp(23) : warning : could be the "Do" in base "A" of class "C"
myprojects\testinheritance\testinheritance.cpp(23) : warning : or the "Do" in base "B" of class "C"

// TestInheritance.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

class A {
public:
int Do (void) { return 1; }
};

class B {
public:
int Do (void) { return 2; }
};

class C: public A, public B {
};

int main(int argc, char* argv[])
{
C CInstance;

printf("Hello World, it\"s %d!\n", CInstance.Do());

return 0;
}


 
Igorek ©   (2004-08-10 17:50) [18]


> Игорь Шевченко ©   (10.08.04 13:47) [13]
> Да я вообще-то не об этом, а зачем смешивать их, создавая
> себе лишние проблемы ?

class T4WheelsCar {
 private:
   bool GoodWheels(void) { /*some diagnostic*/ return true; };
 protected:
   bool WantRepair() { return GoodWheels(); };
};

class TSunBatteryVehicle {
 private:
   bool GoodSunBatteries() { /*some diagnostic*/ return true; };
 protected:
   bool WantRepair() { return GoodSunBatteries(); };
};

class TSunCar: public T4WheelsCar, TSunBatteryVehicle {
 protected:
   bool WantRepair() { return T4WheelsCar::WantRepair() && TSunBatteryVehicle::WantRepair(); };
};


 
Игорь Шевченко ©   (2004-08-10 18:01) [19]

Igorek ©   (10.08.04 17:50) [18]

Вот смотри: в классах T4WheelsCar и TSunBatteryVehicle у тебя методы Good с суффиком. А почему метод WantRepair без суффикса ?


 
Mystic ©   (2004-08-10 19:00) [20]

А зачем смешивать классы с одинаковыми методами ?

Например в Dephi все классы порождены от TObject. Деструктор Destroy у него виртуальный. Если класс порожден от TSomeClass1 и TSomeClass2 и оба перекрывают деструктор, то...

Надо как и в С++ иметьвозможность делать наследование виртуальным. За этим надо следить, ... В целом усложнение языка налицо. А вот реальную пользу можно извлечь в ограниченом количестве случаев. Я, например, против привнесения таких возможностей в язык только для того, чтобы было. Язык должен быть по возможности простым.


 
Igorek ©   (2004-08-11 15:43) [21]


> Игорь Шевченко ©   (10.08.04 18:01) [19]
> Igorek ©   (10.08.04 17:50) [18]
>
> Вот смотри: в классах T4WheelsCar и TSunBatteryVehicle у
> тебя методы Good с суффиком. А почему метод WantRepair без
> суффикса ?

Ну это пример. Метод WantRepair отвечает - надо ли ремонтировать механизм вообще. Для любого класса-механизма такой метод один.
А механизм может иметь несколько частей.
Напр. в классе T4WheelsCar могли бы быть две оси. Тогда был бы еще метод:

GoodAxises() {return GoodAxisFront(/*диагностика*/) && GoodAxisBack(/*диагностика*/); }

Ну и метод WantRepair был бы такой:

bool WantRepair() { return GoodWheels() && GoodAxises(); };

А в наследнике общее состояние состоит из лог. суммы состояний частей.

На самом деле тут налицо проблемма "агрегация vs наследование". Если однотипные обьекты наследуются, то в наследнике вызываются все одинаковые методы предков.
Если агрегируются, то два варианта:
1) агрегируются классы - вызываем все одинаковые методы для полей обьектов
2) агрегируются поля - вызываем конкретную функцию для каждой части

---
я когда писал пример специально привел область, где наследование очевиднее и лучше агрегации


 
Игорь Шевченко ©   (2004-08-11 16:00) [22]


> Ну это пример. Метод WantRepair отвечает - надо ли ремонтировать
> механизм вообще. Для любого класса-механизма такой метод
> один.


Метод Good, насколько я понимаю, отвечает, является ли механизм исправным вообще ?

> bool WantRepair() { return GoodWheels() && GoodAxises();
> };


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

Тогда bool WantRepair () { return !Wheels.Good() || !Axises.Good(); }

И не WantRepair, а NeedsRepair :)


 
DiamondShark ©   (2004-08-11 17:54) [23]

Вообще-то, примерчик на типичную агрегацию.
Так что всё интерфейсами делаем ;)


 
Cobalt ©   (2004-08-11 18:14) [24]

А деструктор по умолчанию - Destroy?


 
DiamondShark ©   (2004-08-11 18:48) [25]


> А деструктор по умолчанию - Destroy?

В паскале отсутствует понятие "деструктор по умолчанию".


 
Cobalt ©   (2004-08-11 20:48) [26]

А как же тогда быть с классами, исполняющими интерфейсы? Их же не уничтожают ручками. А память, выделенную под них, наверное, освобождают как-то корректно?

P.S.
2 DiamondShark © - а у тебя вся спина белая (анкеты нету)



Страницы: 1 вся ветка

Форум: "Потрепаться";
Текущий архив: 2004.08.29;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.033 c
8-1086699491
Ruslan
2004-06-08 16:58
2004.08.29
Формат IMA ADPCM wav файла


14-1092009303
Sergey Kaminski
2004-08-09 03:55
2004.08.29
Никаких домаших животных


14-1092076541
Piter
2004-08-09 22:35
2004.08.29
Помогите с выбором насчет компьютера


1-1092394710
snake1977
2004-08-13 14:58
2004.08.29
QuickReport


14-1092300234
SSSSS
2004-08-12 12:43
2004.08.29
Люди! Где взять лицензионную 5-ю Дельфу?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский