Форум: "Потрепаться";
Текущий архив: 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