Форум: "Прочее";
Текущий архив: 2008.06.01;
Скачать: [xml.tar.bz2];
ВнизКогда же наконец в Delphi for Win32 появятся дженерики Найти похожие ветки
← →
oxffff © (2008-04-15 15:29) [40]
> А тут как получается?
Здесь очень хорошо это получается. А именно.
ACLASS=class
procedure MethodOfClassA();
end;
BCLASS=class
procedure MethodOfClassB();
procedure MethodOfClassC();
end;
ContractA=interface
["{F0B051B7-755B-481D-817C-A78BE6AABDAB}"]
procedure MethodOfClassA();
end;
ContractB=interface
["{2D6EAFD0-3CA8-495D-98A9-95ED3F4A1906}"]
procedure MethodOfClassC();
procedure MethodOfClassB();
end;
CClass=class(TinterfacedObject,ContractA,ContractB)
InstanceA:ACLASS;
InstanceB:BCLASS;
protected
procedure MethodOfClassCLocal();
procedure ContractB.MethodOfClassC=MethodOfClassCLocal;
property InstanceARef:ACLASS read InstanceA implements ContractA;
property InstanceBRef:BCLASS read InstanceB implements ContractB;
public
constructor create;
destructor destroy;override;
end;
← →
oxffff © (2008-04-15 15:32) [41]
> Гы. А указатели и ссылки для кого придуманы? :) И целый
> зоопарк смартпоинтеров туда же.
А что их тоже можно наследовать?
Я поэтому и написал, что это ручками.
← →
Alkid © (2008-04-15 15:32) [42]Т.е. это:
> procedure ContractB.MethodOfClassC=MethodOfClassCLocal;
Перекрывает это:
> property InstanceBRef:BCLASS read InstanceB implements ContractB;
да?
Симпатичненько получается.
← →
vuk © (2008-04-15 15:33) [43]oxffff © (15.04.08 14:32) [20]:
>Вы про ключевое слово implements в Delphi слышали?
Не только слышал но и использовал. И знаю, как оно работает. :)
to Alkid © (15.04.08 15:25) [38]:
>В принципе, виртуальное наследование в С++
>решает подобную проблему. А тут как получается?
Нет.
← →
oxffff © (2008-04-15 15:36) [44]
> Не только слышал но и использовал. И знаю, как оно работает.
> :)
Так привидите пример, что нельзя сделать в Delphi нельзя множественное наследование(подмешивание реализации с жизненным циклом совпадающим с агрегатом).
А я вам покажу как это сделать. :)
← →
Alkid © (2008-04-15 15:36) [45]
> Нет.
Что нет?
"Нет", в смысле, что тут никак не получается
или "Нет", в смысле, что виртуальное наследование в с++ не позвонляет использовать миксины?
← →
jack128_ (2008-04-15 15:37) [46]
> procedure MethodOfClassCLocal();procedure ContractB.MethodOfClassC=MethodOfClassCLocal;
кста, в старших дельфях(в 2007 по крайней мере) - есть глюки, связанные с такой конструкцией. Дельфя - никак не хотела понимать, что СontractB.MethodOfClassC реализуется методом MethodOfClassCLocal, а не тем классом, который в implements сидит.
← →
oxffff © (2008-04-15 15:42) [47]
> Alkid © (15.04.08 15:32) [42]
Более того можно менять семантику копирования агрегируемого RefCount, External RefCount, NoRefCount на лету. Все больше ничего не скажу (это мой секрет). :)
← →
Alkid © (2008-04-15 15:44) [48]
> Более того можно менять семантику копирования агрегируемого
> RefCount, External RefCount, NoRefCount на лету. Все больше
> ничего не скажу (это мой секрет). :)
Вах-вах!
Но вообще, скажем прямо, эта возможность выглядит в дельфи несколько инородно, учитывая что базовая библиотека классов опирается на традиционную гомогенную иерархию классов. Возникает ощущение, что либо "направление развития" языка сильно (кардинально) меняется, либо фитчи начинают добавлять вообще без всякой системы.
← →
oxffff © (2008-04-15 15:51) [49]
> Но вообще, скажем прямо, эта возможность выглядит в дельфи
> несколько инородно, учитывая что базовая библиотека классов
> опирается на традиционную гомогенную иерархию классов.
Наследование есть и остается одиночным. Но существуют способы расширить реализацию по другому.
>Вах-вах!
Полный Вах-вах был когда я этот свой код отлаживал в отладчике. :)
Потом нашел поменял две строчки местами и все заработало.
← →
Kolan © (2008-04-15 15:53) [50]> анонимные функции.
Понял, кажется такое есть в Ruby
← →
Kolan © (2008-04-15 15:54) [51]Кортежи (tuples)
Тоже понял. Вполне логичное название в рел. субд тоже используются.
ХЗ как все это может пригодится…
← →
Alkid © (2008-04-15 15:55) [52]
> Наследование есть и остается одиночным. Но существуют способы
> расширить реализацию по другому.
Дело в том, что этот механизм несколько "конкурирует" с наследованием. :)
Если брать выше, то он представляет собой серьёзную архитектурную альтернативу гомогенным иерархиям, которые традиционны для Дельфи.
ИМХО, дельфи теряет в стройности от этого.
← →
oxffff © (2008-04-15 16:00) [53]
> ИМХО, дельфи теряет в стройности от этого.
Время покажет. Судить не нам.
← →
vuk © (2008-04-15 23:45) [54]to Alkid © (15.04.08 15:36) [45]:
>Что нет?
>"Нет", в смысле, что тут никак не получается
Вопрос там был только один - получается ли такое в Delphi. Ответ ровно на него. Нет, не получается. Потому как наследование даёт новый интерфейс у порожденного класса, а делегирование - нет. Так что, если хочется работать с экземплярами классов, а не ссылками на интерфейсы, то вариант остается только один, тот самый, неудобственный.
to oxffff © (15.04.08 15:36) [44]:
>Так привидите пример, что нельзя сделать в Delphi нельзя множественное
>наследование(подмешивание реализации с жизненным циклом
>совпадающим с агрегатом).
Подмешивание реализации - можно. Множественное наследование - нет, т.к.
множественное наследование приводит к наследованию и интерфейса и реализации. В том же Вашем приведенном примере до методов можно добраться только через запросы интерфейсов, а не прямые вызовы методов у экземпляра.
>А я вам покажу как это сделать. :)
Я же говорю, что надо наоборот. Вы утверждаете, что делегирование - аналог множественного наследования. Вот и доказывайте. А мы посмотрим. :)
← →
ЦУП © (2008-04-16 02:54) [55]
> oxffff © (15.04.08 15:29) [40]
> > А тут как получается?Здесь очень хорошо это получается.
> А именно.ACLASS=classprocedure MethodOfClassA();end;BCLASS=classprocedure
> MethodOfClassB();procedure MethodOfClassC();end;ContractA=interface["{F0B051B7-
> 755B-481D-817C-A78BE6AABDAB}"]procedure MethodOfClassA();
> end;ContractB=interface["{2D6EAFD0-3CA8-495D-98A9-95ED3F4A1906}"]procedure
> MethodOfClassC();procedure MethodOfClassB();end;CClass=class(TinterfacedObject,
> ContractA,ContractB)InstanceA:ACLASS;InstanceB:BCLASS;protectedprocedure
> MethodOfClassCLocal();procedure ContractB.MethodOfClassC=MethodOfClassCLocal;
> property InstanceARef:ACLASS read InstanceA implements ContractA;
> property InstanceBRef:BCLASS read InstanceB implements ContractB;
> publicconstructor create;destructor destroy;override;end;
>
Вахвах... Зачем всё это?
Ну нет множественного наследования в Delphi.
Я бы с удовольствием воспользовался. но увы...
Пример.
Есть две фирмы - TFirm1 и TFirm2.
Способ взаимодействия с каждой - TInteraction1 и TInteraction2, соответственно.
Они производят одинаковый продукт. Одна Продукт1, вторая продукт2. Эти продукты отличаются только качеством. У одной фирмы процесс производства TProcess1, у второй - TProcess2.
Есть третья фирма, которая обединила обе. Хотелось бы не агрегированием, а прямым наследованием производить товары третьей фирмой.
> oxffff ©
А что, есть примеры реализации в наследниках каких либо классов(путь даже есть интерфейсы) множественного наследования?
В 32 и 40 всего лишь примеры агрегирования. Не так ли?
← →
ЦУП © (2008-04-16 02:57) [56]
> Alkid © (15.04.08 15:55) [52]
ИМХО, дельфи теряет в стройности от этого.
Delphi ничего не теряет.
То, что есть, то и есть.
В любом случае в Delphi всё реализуемо.
Вопрос возник из-за того, что не всё есть в Delphi.
← →
oxffff © (2008-04-16 09:29) [57]
> vuk © (15.04.08 23:45) [54]
> to Alkid © (15.04.08 15:36) [45]:
> >Что нет?
> >"Нет", в смысле, что тут никак не получается
> Вопрос там был только один - получается ли такое в Delphi.
> Ответ ровно на него. Нет, не получается. Потому как наследование
> даёт новый интерфейс у порожденного класса, а делегирование
> - нет. Так что, если хочется работать с экземплярами классов,
> а не ссылками на интерфейсы, то вариант остается только
> один, тот самый, неудобственный.
Да ну?
Делегирование реализации - это просто способ переноса ответственности по контракту или его части другому лицу (у которого жизненный цикл может, а может и не совпадать).
class(TinterfacedObject,ContractA,ContractB)
Таким образом вы объявляя, что класс поддерживает ContractA
и ContractB.
Если вам не нравится (по скорости) способ вызова через VMT интерфейса
ContractA метода.
А именно ContractA(A).MethodOfClassA;
То делайте так
A.InstanceARef.MethodOfClassA; <- (С++ делает тоже самое неявно за тебя).
Но у Delphi есть преимущество в том, что ты можешь настраивать перенос ответственности полностью или частично, также как и настраивать перенос ответственности по одному контракту на разные агрегаты.
> to oxffff © (15.04.08 15:36) [44]:
> >Так привидите пример, что нельзя сделать в Delphi нельзя
> множественное
> >наследование(подмешивание реализации с жизненным циклом
>
> >совпадающим с агрегатом).
> Подмешивание реализации - можно. Множественное наследование
> - нет, т.к.
> множественное наследование приводит к наследованию и интерфейса
> и реализации. В том же Вашем приведенном примере до методов
> можно добраться только через запросы интерфейсов, а не прямые
> вызовы методов у экземпляра.
Да не нужно нам множественное наследование,
НЕ НУЖНО В том виде как в С++. Мы еще ниже поговорим про артефакты
Добиваемся того же самого используя делегирование реализациии ( наследование это тоже самое по сути). И вы прекрасно знаете почему.
class classA: public ClassB, public ClassC Тоже самое что и
class classA
{
ClassB B;
ClassC C;
}
C той лишь разницей, что ClassB, ClassC scope натягивается на ClassA.
И при вызове компилятор за вас подстраивает Offset до агрегата.
Но не забываем, что не у вас возможности просто менять часть реализации.
A.InstanceARef.MethodOfClassA;
← →
Игорь Шевченко © (2008-04-16 09:34) [58]oxffff © (16.04.08 09:29) [57]
> Да не нужно нам множественное наследование,
> НЕ НУЖНО В том виде как в С++. Мы еще ниже поговорим про
> артефакты
Это вам не нужно. Не надо говорить за всех.
← →
oxffff © (2008-04-16 09:41) [59]В этом примере.
class classA
{
public:
virtual void MethodA() {};
};
class classB
{
public:
virtual void MethodB() {};
};
class classC: public classA , public classB
{
//virtual void MethodB() {};
};
classC содержит два агрегата classA, classB.
Также как и два vfptr у каждого агрегата.
Хотите поговорить про артефакты (затраты на вызов при виртуальном наследовании) в С++. А именно про indirect обращение через
virtual base pointer(s) (vbptr)?
← →
oxffff © (2008-04-16 09:43) [60]
> Игорь Шевченко © (16.04.08 09:34) [58]
> oxffff © (16.04.08 09:29) [57]
>
>
> > Да не нужно нам множественное наследование,
> > НЕ НУЖНО В том виде как в С++. Мы еще ниже поговорим про
>
> > артефакты
>
>
> Это вам не нужно. Не надо говорить за всех.
Ну насколько я знаю вам это не нужно. Не так ли?
← →
Игорь Шевченко © (2008-04-16 10:01) [61]oxffff © (16.04.08 09:43) [60]
Иногда бывает нужно и берет досада, что нету.
← →
oxffff © (2008-04-16 10:12) [62]
>
> Игорь Шевченко © (16.04.08 10:01) [61]
> oxffff © (16.04.08 09:43) [60]
>
> Иногда бывает нужно и берет досада, что нету.
Для того чтобы достичь цели не нужно его вводить.
Привидите пример когда у вас эта возникла и почему?
И что вам мешало и ограничивало в Delphi?
← →
Игорь Шевченко © (2008-04-16 10:23) [63]oxffff © (16.04.08 10:12) [62]
> Для того чтобы достичь цели не нужно его вводить.
Я понимаю, я же выхожу из положения. Но неудобно.
> Привидите пример когда у вас эта возникла и почему?
А смысл ? Решение найдено существующими средствами, собственно и не одно. Можно же вообще обходиться без наследования, как множественного, так и одиночного, можно обходиться без инкапсуляции и полиморфизма, все будет работать, уверяю.
← →
oxffff © (2008-04-16 10:24) [64]
> Игорь Шевченко © (16.04.08 10:01) [61]
> oxffff © (16.04.08 09:43) [60]
>
> Иногда бывает нужно и берет досада, что нету.
Есть предположение, что если его ввести (а я остаюсь при мнении что это не нужно) это напрочь поломает структуру Tobject.
Какое решение принимать при вызове AfterContruction и BeforeDestruction.
Делать автоматом или как?
Далее как решать конфликт Idx при вызове динамических методов.
и я уверен это еще не все.
Я конечно уверен что это все решаемо.
← →
oxffff © (2008-04-16 10:30) [65]
> собственно и не одно.
И я о том же.
← →
oxffff © (2008-04-16 10:35) [66]
> Я понимаю, я же выхожу из положения. Но неудобно.
Может вы не так что то делаете?
← →
vuk © (2008-04-16 10:54) [67]to oxffff © (16.04.08 09:29) [57]:
>Если вам не нравится (по скорости) способ вызова через VMT интерфейса
>ContractA метода.
>А именно ContractA(A).MethodOfClassA;
>То делайте так
>A.InstanceARef.MethodOfClassA;
Фтопку. Ибо нарушение инкапсуляции.
← →
Игорь Шевченко © (2008-04-16 11:02) [68]
> (а я остаюсь при мнении что это не нужно)
да и одиночное наследование тоже как бы не особенно к чему.
← →
oxffff © (2008-04-16 11:26) [69]
> vuk © (16.04.08 10:54) [67]
> to oxffff © (16.04.08 09:29) [57]:
>
> >Если вам не нравится (по скорости) способ вызова через
> VMT интерфейса
> >ContractA метода.
> >А именно ContractA(A).MethodOfClassA;
>
> >То делайте так
> >A.InstanceARef.MethodOfClassA;
> Фтопку. Ибо нарушение инкапсуляции.
Вы просто не имеете их готовить.
Где нарушение инкапсуляции?
Доступ к членам A.InstanceARef согласно области видимости
Private, protected, public класса объекта InstanceARef.
А что касается ContractA(A).MethodOfClassA так вы определите public подмножество ContractA.
Не надо натягивать идеалогию видимости из С++ на Delphi.
← →
vuk © (2008-04-16 11:42) [70]to oxffff © (16.04.08 11:26) [69]:
>Вы просто не имеете их готовить.
А вот это уже не Вам судить. Ага? :)
>Где нарушение инкапсуляции?
В Вашем же примере свойство InstanceARef имеет область видимости protected. Стало быть клиенту не доступно и пока всё нормально. Но вот если есть желание вызывать как A.InstanceARef.MethodOfClassA, то нужно делать public. Что открывает доступ клиенту к тому, к чему, по-хорошему, у него доступа быть не должно.
← →
oxffff © (2008-04-16 12:02) [71]
> vuk © (16.04.08 11:42) [70]
> to oxffff © (16.04.08 11:26) [69]:
> >Вы просто не имеете их готовить.
> А вот это уже не Вам судить. Ага? :)
>
> >Где нарушение инкапсуляции?
> В Вашем же примере свойство InstanceARef имеет область видимости
> protected. Стало быть клиенту не доступно и пока всё нормально.
> Но вот если есть желание вызывать как A.InstanceARef.MethodOfClassA,
> то нужно делать public. Что открывает доступ клиенту к
> тому, к чему, по-хорошему, у него доступа быть не должно.
>
Судить не мне. Мне это не нужно. Однако хочу отметить
> Но вот если есть желание вызывать как A.InstanceARef.MethodOfClassA,
> то нужно делать public. Что открывает доступ клиенту к
> тому, к чему, по-хорошему, у него доступа быть не должно.
>
Я так понимаю есть желание у составного объекта сделать вызов у агрегата?
Так определите их в одном модуле.
Либо сделайте public, а составном объекте (в примере так и сделано) в protected.
protected
property InstanceARef:ACLASS read InstanceA implements ContractA;
Таким образом все согласно идеалогии Delphi.
← →
Игорь Шевченко © (2008-04-16 12:04) [72]
> Так определите их в одном модуле.
Проще сделать все public
← →
vuk © (2008-04-16 12:16) [73]to oxffff © (16.04.08 12:02) [71]:
>Я так понимаю есть желание у составного объекта сделать вызов у
>агрегата?
Речь вообще не о том. Попробую объяснить немного иначе. Я хочу сказать, что множественное наследование помимо наследования реализации приводит к формированию некоего нового контракта на основе нескольких исходных контрактов. И при этом клиент может ничего не знать об исходных. С интерфейсами все обстоит иначе. Никакого нового контракта не возникает и клиент оперирует исходными контрактами. Так понятнее?
И именно поэтому тот прием с mix-in из C++ аналога в Delphi не имеет.
← →
oxffff © (2008-04-16 12:43) [74]
> Речь вообще не о том. Попробую объяснить немного иначе
Ну судя по
>вот если есть желание вызывать как A.InstanceARef.MethodOfClassA,
> то нужно делать public.
Как как раз о том.
Теперь ответ на ваш новый вопрос.
Действительно компилятор не обрабатывает конструкцию вида
procedure ContractD.MethodOfClassC=InstanceB.InstanceBRef;
Для наследования от двух решение есть. наследуете от одного, делегируете второму с общим контрактом.
ContractD=interface
["{F283C2A5-05A9-4772-A0FB-46CE18C74218}"]
procedure MethodOfClassC();
procedure MethodOfClassB();
procedure MethodOfClassA();
end;
Для трех и более компилятор не поддерживает конструкцию вида
procedure ContractD.MethodOfClassC=InstanceB.InstanceBRef;
Однако ее можно написать самому. и сделать метод Inline.
Либо написать в Codegear. Нужно слегка поправить синтаксис.
Не принципиально.
← →
oxffff © (2008-04-16 14:17) [75]
> Речь вообще не о том. Попробую объяснить немного иначе.
> Я хочу сказать, что множественное наследование помимо наследования
> реализации приводит к формированию некоего нового контракта
> на основе нескольких исходных контрактов. И при этом клиент
> может ничего не знать об исходных. С интерфейсами все обстоит
> иначе. Никакого нового контракта не возникает и клиент оперирует
> исходными контрактами. Так понятнее?
После обеда у меня вот какие мысли.
Вы говорите об общем контракте производного типа. Поэтому для использования этого контракта клиенты должны знать об этом типе(либо его производных).
В таком случае возникает вопрос, если клиент использует конкретный тип (либо производные от него), если какая то разница использовать общий контракт или котракты разделенные по функциональности?
Страницы: 1 2 вся ветка
Форум: "Прочее";
Текущий архив: 2008.06.01;
Скачать: [xml.tar.bz2];
Память: 0.64 MB
Время: 0.052 c