Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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.54 MB
Время: 0.024 c
1-1089892632
nastya
2004-07-15 15:57
2004.08.01
печать нескольких списков в одном отчете


4-1087814076
Users
2004-06-21 14:34
2004.08.01
CreateFile для привода CD


3-1089385289
SOS
2004-07-09 19:01
2004.08.01
подскажите как задать параметр ADOQuery1.Parameters????


1-1090096184
Огромное Кулясищще
2004-07-18 00:29
2004.08.01
Скопировать в буфер обмена несколько строк.


1-1089987052
Клафк
2004-07-16 18:10
2004.08.01
В Делфи 6 неизвестная ошибка!