Текущий архив: 2004.08.01;
Скачать: CL | DM;
ВнизНаследование компонента... Найти похожие ветки
← →
Rouse_ © (2004-07-13 21:27) [0]Тема, конечно интересная, но по сути своей более подходит именно к потрепаться, так как я хочу обсудить технологию наследования неких компонентов (написания их более развитых вариантов).
Итак:
Как наследоваться от TButton все прекрасно понимают и как добавить к нему нукую новую функциональность тоже... но вот возник у меня вопрос:
К примеру возьмем компонент наподобие ServerSocket (ну я сам сетевик, поэтому это самая понятная лично для меня аналогия :)
Что он может иметь:
некий слушающий сокет
и "массив" (неважно как он там реализован, хотябы через коллекции) рабочих сокетов...
Т.е. имеем компонент который содержит в себе себя (сори за каламбур) и массив неких объектов.
Теперь ситуация:
Мы хотим развить данный компонент. Все довольно просто:
1. наследуемся от него.
2. обьявляем необходимые свойства, функции процедуры, переопределяем при необходимости
3. выводум нужную нам функциональность в public/published
а вот теперь сама загвоздка:
представьте что расширить нужно не него, а класс представляющий собой массив включенных в него элементов.
В приведеном выше примере им выступит конечный сокет.
К примеру он имеет некий набор событий-свойств, но мне нужно добавить к нему еще одно свойство (ну для простоты некий property Register: Boolean read FRegister write FRegister;)
и вот что тогда предстоит:
Предстоит практически полностью переписать главный компонент, только из-за того что у одной из его переменных (массива объектов) добавилось новое свойство?
Это не есть неудобно.
Или я не вижу очевидных вещей или раскажите мне как вы решаете данные ситуации...
Заранее спасибо :)
← →
Rouse_ © (2004-07-13 21:31) [1]> Это не есть неудобно.
Читать как "Это не есть удобно" :)
Сори :)
← →
jack128 © (2004-07-13 22:06) [2]Нечего не понял.
Саш, а можно пример не из сетей?
А то тут
> и "массив" (неважно как он там реализован, хотябы через
> коллекции) рабочих сокетов...
> представьте что расширить нужно не него, а класс представляющий
> собой массив включенных в него элементов.
то есть коллекцию? Но дальше
> В приведеном выше примере им выступит конечный сокет
кто есть конечный сокет? тот который > наподобие ServerSocket или тот, который > некий слушающий сокет или может один из >рабочих сокетов...
Можно какой нить пример, пусть не имеющий смысла, но на основе того же button"a , а не этого многоликого сокета? :-)
← →
Style © (2004-07-13 22:15) [3]
> Rouse_ © (13.07.04 21:31) [1]
Саня, я тоже ничего не поняL :) Можеть тебе в отпуск уже пора?? :))
← →
Ломброзо © (2004-07-13 22:16) [4]В спецификации COM проблему предложено решать совместимостью на уровне интерфейсов. Пусть кокласс версии 1.0 реализует какой-то интерфейс. Если нужно расширить функционал, необходимо отнаследовать второй интерфейс от первого, и тоже выставить его наружу (кокласс версии 2.0). Клиент по выбору может работать с любым интерфейсом из двух, причём во избежание ошибок доступа проверку можно осуществлять либо на этапе компиляции, либо в Run-time (QueryInterface). В Delphi в общем-то примерно то же самое можно сделать при помощи обычного наследования, используя RTTI, только код будет пестреть всякими там is и as.
← →
Григорьев Антон © (2004-07-13 22:17) [5]Вообще, можно сделать это через метаклассы и виртуальные конструкторы. Пусть тип-контейнер имеет свойство указателя на класс, объекты которого он содержит. Породил наследника от содержащегося класса - меняй это свойство у контейнера. Правда, придётся каждый раз приводить типы, чтобы получить доступ к новым полям и методам внутреннего класса.
← →
Слабак (2004-07-13 22:27) [6]А представьте такую ситуацию. Умирает ваш-дед миллионер, в завещании все деньги передает в разные там фонды, а про вас пишет что нибуть вроде: "А этому бездельнику я наследую компонент"
Я бы деда еще разок убил
← →
Григорьев Антон © (2004-07-13 22:30) [7]
> Слабак (13.07.04 22:27) [6]
А что-нибудь по делу сказать - никак?
← →
Слабак (2004-07-13 22:39) [8]
> Григорьев Антон
Было бы как - сказал бы ))
В программировании я слабак ))
← →
Ломброзо © (2004-07-13 22:51) [9]>Слабак (13.07.04 22:39) [8]
То есть Вас сюда случайно занесло?
← →
Mim1 © (2004-07-13 22:52) [10]Rouse_ © (13.07.04 21:27)
А хорошо что вы про колекшены вспомнили, там ведь мы расширяем вложенные в него элементы.
Так же можно посмотреть чтото вроде TTreeView.OnCreateNodeClass.
Однако если разработчиком этого не предусмотрено будет тяжелее :(
← →
Слабак (2004-07-13 22:55) [11]
> Ломброзо
Иногда на этом сайте читаю ПОТРЕПАТЬСЯ. Тут смешные люди есть )))
Я надеюсь здесь залетных не выгоняють???
← →
Ломброзо © (2004-07-13 22:59) [12]Нет, залётные здесь сперва вьют гнездо, потом долго и громко щёлкают клювом, но в конце концов полюбившимся всем пернатых друзей отправляют в муфельную печь. Изучать изнутри.
← →
Rouse_ © (2004-07-13 23:22) [13]Хорошо, попробую обьяснить...
Посмотрите вот сюда: > [10] Mim1 © (13.07.04 22:52)
Именно, что я и имел ввиду...
Давайте построим тестовый компонент...
TTestItem = class(TPersistent)
private
AProperty: Boolean;
//BProperty: Boolean;
public
property A: Boolean read AProperty write AProperty;
//property B: Boolean read BProperty write BProperty;
end;
TTestComponent = class(TComponent)
private
FTest: TTestItem;
function GetTestItem: TTestItem;
public
property TestAProperty: Boolean read GetTestItem;
end;
Изначально мы имеем доступ к TTestItem у каторого есть только property A, а вот захотелось мне его расширить чтобы не меняя TTestComponent у TTestItem появилось закоментированное property B
Дело в том что компонент предок ничего не знает что я пытаюсь его расширить TTestItem до property В и поэтому вызов "TTestComponent.FTest.В " не пропустит сам компилятор
Так понятно? Или я все же неясно выражаюсь...
← →
Rouse_ © (2004-07-13 23:28) [14]Во, даже лучше пример придумал...
Представьте (на примере того же буттона) - у нее есть TFont. Так вот нам необходимо написать предок TButton с расширеным TFont (ну к примеру наш TFont будет иметь свойство градиентной заливки :)
← →
Style © (2004-07-13 23:35) [15]
> (ну к примеру наш TFont будет иметь свойство градиентной
> заливки :)
Ну так наследуемся от TFont и добавляем свойства градиентной заливки. наследуемся от Баттона и меняем TFont.. и Paint?
Или тебе надоело все ручками писать ??
← →
Rouse_ © (2004-07-14 00:07) [16]> Ну так наследуемся от TFont и добавляем свойства градиентной
> заливки. наследуемся от Баттона и меняем TFont.. и Paint?
> > Или тебе надоело все ручками писать ??
Хе... примерный код плз ;)
ЗЫ: что ж ты думал я просто так тему завел? ;)
← →
Cobalt © (2004-07-14 00:14) [17]2 Rouse_ ©
Тут вспоминается Фаронов, ТП 7.0 и его пример с коллекцией и полиморфизмом, правда там в коллекцию добавлялись элементы "извне" коллекции.
А у тебя элементы создаются изнутри коллекции, так?
← →
Rouse_ © (2004-07-14 00:26) [18]Именно так...
В качестве еще более наглядного приера
http://www.delphikingdom.ru/asp/viewitem.asp?UrlItem=/helloworld/tcollection.htm
Представьте что:
TSpot = class(TCollectionItem)
private
FCenterX: integer;
FCenterY: integer;
FColor: TColor;
public
constructor Create(Collection: TCollection); override;
function GetGuid: lpwUUID;
published
property CenterX: integer read FCenterX write SetCenterX default 3;
property CenterY: integer read FCenterY write SetCenterY default 3;
property Color: TColor read FColor write SetColor default clBlack;
end;
(да, мы поимели новую функцию...)
Но дело то в том что если наследоваться от него то тогда придется переписать TSpotCollection = class(TCollection)
а после этого и сам TDappledShape = class(TShape)
Потому что они и понятия о ней не имеют и вообще в DCU находятся...
← →
Rouse_ © (2004-07-14 00:34) [19]> [2] jack128 © (13.07.04 22:06)
> [3] Style © (13.07.04 22:15)
Жень, Сереж... тут все очень просто...
Я забыл выделить главную фразу "расширить нужно не него, а класс представляющий собой массив включенных в него элементов" и этим ввел вас обоих в заблуждение...
Мои извинения...
← →
Rouse_ © (2004-07-14 00:39) [20]> Style ©
Блин, чур меня, Петр Сергеевич, есессно :)))
← →
Юрий Зотов © (2004-07-14 06:34) [21]> Rouse_
Вот вариант решения с минимальной перепиской контейнера (насколько я понял, его и имел в виду Антон).
TMyBaseObject = class(...)
...
constructor Create; virtual;
end;
TMyBaseObjectClass = class of TMyBaseObject;
TMyObject1 = class(TMyBaseObject)
...
property A...;
end;
TMyObject2 = class(TMyBaseObject1)
...
property B...;
end;
TMyContainer = class(...)
private
FMyObject: TMyBaseObject;
protected
class function GetMyObjectClass: TMyBaseObjectClass; virtual;
public
constructor Create;
...
property MyObject: TMyBaseObject...
end;
constructor TMyContainer.Create;
begin
inherited;
FMyObject := GetMyObjectClass.Create
end;
class function TMyContainer.GetMyObjectClass: TMyBaseObjectClass;
begin
Result := TMyObject2
end;
Если надо изменить внутренний объект, в контейнере потребуется заместить всего один метод. А неудобство в том, что придется часто приводить тип:
TMyObject2(MyContainer.MyObject).B := ...
← →
SPeller © (2004-07-14 07:29) [22]Я думаю что всё очень просто и никаких проблем нет. Переписать класс-предок нужно будет только там, где он создаёт объект. Просто заставить его создавать не TMyClass1, а TMyClass2. В остальном коде предку будет абсолютно начхать на подмену. А в потомке для доступа к новой функциональности придётся кадый раз приводить тип, но чтобы не загромождать конструкциями as/is, можно просто TMyClass2(SomeProperty).XXX; Вот и всё.
← →
SPeller © (2004-07-14 07:32) [23]... Или заводить переменную
sv: TMyClass2;
begin
sv := TMyClass2(SomeProp);
...
И дальше работать уже с переменной sv.
← →
SPeller © (2004-07-14 07:35) [24]
> Предстоит практически полностью переписать главный компонент,
> только из-за того что у одной из его переменных (массива
> объектов) добавилось новое свойство?
Зачем? Если вы измените дочерний компонент, то основному тоже будет начхать на новую функциональность, он просто не будет к ней обращаться и работать с тем что было. КОнечно, если основной компонент не в dcu.
Страницы: 1 вся ветка
Текущий архив: 2004.08.01;
Скачать: CL | DM;
Память: 0.52 MB
Время: 0.041 c