Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.12.07;
Скачать: CL | DM;

Вниз

Открытие методов класса внутри другого класса   Найти похожие ветки 

 
Буум   (2008-10-02 15:18) [0]

Иногда возникает такая ситуация - допустим, есть некий класс, выполняющий некий функционал:

TLittleClass = class
 function Delete ;
 function Paint;
end;


Есть класс, который внутри имеет экземпляр данного класса:

TBigClass = class
private/public
 FLittle: TLittleClass;
public
 function Delete;
 function Paint;
...
end;


А реализация аля типа такого:

function TBigClass.Delete;
begin
 FLittle.Delete;
 TextToLog("Delete Complete");
end;

function TBigClass.Paint;
begin
 FLittle.Paint;
end;


Если словами - то в классе (TBigClass) есть экземпляр другого класса (TLittleClass), который выполняет некий функционал.

При этом TBigClass должен ИНОГДА знать, когда дергаются методы TLittleClass. Возникает вопрос как это все организовать.

С одной стороны экземпляр TLittleClass можно вывести в public секцию TBigClass, вызовы будут аля:
TBigClass.Little.Delete;
Тогда BigClass не узнает о вызове методов LittleClass.

Можно сделать в BigClass прослойки в виде методов. Но если метод:

function TBigClass.Delete;
begin
 FLittle.Delete;
 TextToLog("Delete Complete");
end;


Выглядит еще более менее, то чисто прослойки:

function TBigClass.Paint;
begin
 FLittle.Paint;
end;


выглядят глупо.

Еще можно в TLittleClass делать события, на которые подписывать TBigClass... Но как-то сложновыглядит.

Кто какой способ выбирает (возможно иные)?

P.S. Логично было б сказать, что TBigClass нужно наследовать от TLittleClass, но это невозможно по причине того, что TBigClass уже наследовался от какого-то базового класса, а множественного наследования вроде как нету в D...


 
KSergey ©   (2008-10-02 15:22) [1]

> Буум   (02.10.08 15:18)  
> P.S. Логично было б сказать, что TBigClass нужно наследовать
> от TLittleClass, но это невозможно по причине того, что
> TBigClass уже наследовался от какого-то базового класса,
>  а множественного наследования вроде как нету в D...

А наследование может быть очень даже глубоко вложенным и его множественность тут ни при чем.


 
Плохиш ©   (2008-10-02 15:35) [2]


> P.S. Логично было б сказать, что TBigClass нужно наследовать
> от TLittleClass, но это невозможно по причине того, что
> TBigClass уже наследовался от какого-то базового класса,
>  а множественного наследования вроде как нету в D...

Ты больше такой литературы не кури.


 
Ega23 ©   (2008-10-02 15:39) [3]


> С одной стороны экземпляр TLittleClass можно вывести в public
> секцию TBigClass, вызовы будут аля:
> TBigClass.Little.Delete;
> Тогда BigClass не узнает о вызове методов LittleClass.


type

 TLittleClassEvent = procedure () of object;

TLittleClass = class
private
 FOnDelete : TLittleClassEvent;
public
 procedure Delete;
 property OnDelete : TLittleClassEvent read FOnDelete write FFOnDelete;
end;

TBigClass = class
private
 FLittle := TLittleClass;
 procedure OnLittleDelete;
public
 constructor Create;
 destructor Destroy; override;
 property Littlte : TLittleClass read FLittle;
end;

procedure TLittleClass.Delete;
begin
 // удаляем чо надо
 if Assigned(FOnDelete) then
   FOnDelete;
end;

constructor TBigClass.Create;
begin
 inherited;
 FLittle := TLittleClass.Create;
 FLittle.OnDelete := OnLittleDelete;
end;

destructor TBigClass.Destroy;
begin
 FLittle.Free;
 inherited;
end;

procedure TBigClass.OnLittleDelete;
begin
 TextToLog("Delete Complete");
end;


Как-то так.


 
Плохиш ©   (2008-10-02 15:42) [4]


> Ega23 ©   (02.10.08 15:39) [3]

Зачем городить такой геморрой, если есть возможность изменить исходный класс TLittleClass?


 
pasha_golub ©   (2008-10-02 15:44) [5]


> Еще можно в TLittleClass делать события, на которые подписывать
> TBigClass... Но как-то сложновыглядит.

Разработчики VCL так не считают. Например, TQuery.SQL: TStrings. Подвешен обработчик на изменение.


 
jack128_   (2008-10-02 15:46) [6]

ILittle = interface
function Delete ;
function Paint;
end;
TLittle = class(TObject, ILittle)
function Delete ;
function Paint;
end

TBigClass = class(TObject, ILittle)
private
 FLittle: TLIttle;
 property Little: TLittle read FLittle implements ILIttle;
 procedure ILittle.Delete = MyDelete;
 procedure MyDelete;
end

procedure TBigClass.MyDelete;
begin
FLittle.Delete;
TextToLog("Delete Complete");
end;

соответственно вместо TBigClass используешь ILittle


 
pasha_golub ©   (2008-10-02 15:50) [7]

Ну, Жека, намудрил. :0)


 
KSergey ©   (2008-10-02 15:51) [8]

> pasha_golub ©   (02.10.08 15:44) [5]

Это да, но есть подозрение, что в описанной задаче автору оно не нужно.
Т..к если класс вложен в другой как private, то каждый из них совершенно точно знает когда и какой из его методов вызывается. Так же внешний класс всегда точно знает когда и какие методы вложенного вызывается.
А если начать уведомлять при такой схеме вложенный класс о вызовах методов родителя - то возникнет дикая каша.


 
jack128_   (2008-10-02 15:52) [9]


> Ega23 ©   (02.10.08 15:39) [3]

будет 10 таких методов - будешь десять событий делать ?? не многовато ?


 
Плохиш ©   (2008-10-02 15:53) [10]


> jack128_   (02.10.08 15:46) [6]

[4]


 
oxffff ©   (2008-10-02 15:53) [11]


> function TBigClass.Paint;
> begin
>  FLittle.Paint;
> end;


function TBigClass.Paint;inline
begin
FLittle.Paint;
end;


 
Ega23 ©   (2008-10-02 15:56) [12]


> будет 10 таких методов - будешь десять событий делать ??
>  не многовато ?


Я проектировать так не буду...  :)


 
oxffff ©   (2008-10-02 15:57) [13]


> Выглядит еще более менее, то чисто прослойки:
>
> function TBigClass.Paint;
> begin
>  FLittle.Paint;
> end;
>
> выглядят глупо.


Я бы не стал употреблять слово глупо. Есть понятия агрегирования, делегирования, наследования,использования. Это не глупые понятия. :)


 
Игорь Шевченко ©   (2008-10-02 16:07) [14]

гуру рекомендуют следующее: тот, кто использует внешний класс, не должен знать об его устройстве. То есть, BigClass.FLitteClass.Paint - это есть ересь, за которую гореть в вечном адском огне.

Но тем не менее, это наиболее простой и быстрый способ.


 
{RASkov} ©   (2008-10-02 16:08) [15]

> P.S. Логично было б сказать, что TBigClass нужно наследовать
> от TLittleClass, но это невозможно по причине того, что
> TBigClass уже наследовался от какого-то базового класса,
> а множественного наследования вроде как нету в D...

А если вот так:

TBigClass = class(TBaseClass)
.....
end;

TClass = class(TBigClass)
 procedure Delete;
 procedure Paint;
end;

?
Что-то я не в теме наверное :(
Но если так не пойдет, то в [0] вроде тоже нормально..... А как иначе? [6] - тоже придется структуру менять... т.е. как и тут я предлогаю...


 
oxffff ©   (2008-10-02 16:11) [16]


> Игорь Шевченко ©   (02.10.08 16:07) [14]


oxffff ©   (02.10.08 15:53) [11]
Позволяет при сходной скорости вызова, не раскрывать тайны делегата.


 
oxffff ©   (2008-10-02 16:17) [17]


> jack128_   (02.10.08 15:46) [6]
> ILittle = interface
> function Delete ;
> function Paint;
> end;
> TLittle = class(TObject, ILittle)
> function Delete ;
> function Paint;
> end
>
> TBigClass = class(TObject, ILittle)
> private
>  FLittle: TLIttle;
>  property Little: TLittle read FLittle implements ILIttle;
>
>  procedure ILittle.Delete = MyDelete;
>  procedure MyDelete;
> end
>
> procedure TBigClass.MyDelete;
> begin
> FLittle.Delete;
> TextToLog("Delete Complete");
> end;
> соответственно вместо TBigClass используешь ILittle


Можно просто

TLittle = class(TObject)
function Delete ;
function Paint;
end


 
jack128_   (2008-10-02 16:35) [18]


> oxffff ©   (02.10.08 16:17) [17]

а как тогда использовать TBigClass  ??


 
DVM ©   (2008-10-02 16:56) [19]


> то чисто прослойки:
>
> function TBigClass.Paint;
> begin
>  FLittle.Paint;
> end;
>
> выглядят глупо.

Нормально выглядит. Особенно хорошо это выглядит, когда используешь чужой класс и не приходится изучать что внутри него надо дергать.


 
Буум   (2008-10-02 17:02) [20]


> А наследование может быть очень даже глубоко вложенным и
> его множественность тут ни при чем


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

Ega23, тебя я понял. Ты реализовал:

>Еще можно в TLittleClass делать события, на которые подписывать TBigClass

jack128_, тебя тоже понял, множественное наследование через интерфейсы.


> тот, кто использует внешний класс, не должен знать об его
> устройстве. То есть, BigClass.FLitteClass.Paint - это есть
> ересь, за которую гореть в вечном адском огне


так а каков ваш вариант?


 
Буум   (2008-10-02 17:04) [21]


> Особенно хорошо это выглядит, когда используешь чужой класс
> и не приходится изучать что внутри него надо дергать


вот именно ;) Но если таких прослоек-методов много (с десяток допустим), при этом "перекрыты" только пара - выглядит не кузяво ;)


 
oxffff ©   (2008-10-02 17:19) [22]


> jack128_   (02.10.08 16:35) [18]
>
> > oxffff ©   (02.10.08 16:17) [17]
>
> а как тогда использовать TBigClass  ??


Я  имею ввиду, что ты делаешь geletate to class type property

Вместо TLittle = class(TObject, ILittle) в твоем коде достаточно,

TLittle = class(TObject)

Таким образом ты еще не вмешиваешься в класс делегат.


 
jack128_   (2008-10-02 17:26) [23]

а. Ну да.



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

Текущий архив: 2008.12.07;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.015 c
2-1224924753
Gurd
2008-10-25 12:52
2008.12.07
StringGrid.RowHeight:=0


1-1203111617
Blind Guardian
2008-02-16 00:40
2008.12.07
Сравнение последовательностей вещественных чисел на сходство


2-1225118500
НовичОК89
2008-10-27 17:41
2008.12.07
получить Коды символов-разделителй


2-1225186805
dmitry_12_08_73
2008-10-28 12:40
2008.12.07
Скрытие пиктограммы программы в таскбаре


2-1225273309
Iriss
2008-10-29 12:41
2008.12.07
Процедура внутри процедуры