![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Чем отличается в классах Free от Destroy?
Kiloper © (2006-08-09 11:34:00)Чем отличается в классах Free от Destroy? Так и так работает?
evvcom (2006-08-10 14:13:00) [1]> [22] Kolan © (10.08.06 14:07)
> Что становится генофондом?
Код, библиотека, которые в общем-то уже предназначены для использования в прикладных целях.
evvcom (2006-08-10 14:08:00) [2]> [21] Kolan © (10.08.06 13:52)
Да там особо и смотреть нечего. Ты DevExpress (dxGrid, dxTreeList) по возможности посмотри и попробуй написать и зарегить свои классы столбцов. Вот там есть чему поучиться, настолько гибко написано. Да такое, наверняка, и в других продвинутых библиотеках найдешь.
Kolan (2006-08-10 14:07:00) [3]Перечитал
> который в данном случае становится генофондом, а про генофонд,
> надеюсь, уже все знают
Что становится генофондом?
Kolan (2006-08-10 13:52:00) [4]Ну это я так себе это понял. Мож и не верно.
Тут смотри:
Виртуальный конструктор Create класса TComponent
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1154509872&n=0
evvcom (2006-08-10 13:50:00) [5]> [18] Kolan © (10.08.06 13:41)
Но я бы не назвал это косвеннымсозданием.
В твоем примере аргумент, что надо заменить по тексту имя класса в одном или 2-х местах, это не аргумент. Вот если бы ты сказал, что не нужно будет совсем править чужой код (который в данном случае становится генофондом, а про генофонд, надеюсь, уже все знают), вот это аргумент.
Kolan (2006-08-10 13:42:00) [6]
> инстанцировать конктретные экземпляры
инстанцировать экземпляры конкретных классов.
Kolan (2006-08-10 13:41:00) [7]Те не надо обявлять конктреные типы как например тут:
> var
> Obj: TChild;
А следует делать абстрактных предков. Обявлять переменные как предки, а инстанцировать конктретные экземпляры:
Пример:
var
S: TStrings;
begin
S := TStringList.Create;
try
{..}
finally
Free;
end;
end;
Чем это полезно? - Тем что если я потом сделаю наследникаTStrings, напримерTMyOwnStringList, то мне нудно будет заменить только строчку выделенную жирным.
А если я написал бы так:
var
S: TStringList;
begin
S := TStringList.Create;
try
{..}
finally
Free;
end;
end;
То уже в двух местах...
Понятно что это простейший пример. Тут это нестроашно, а в большой системе...
Kolan (2006-08-10 13:33:00) [8]
> Как это? Что за понятие?
Продолжение цитаты:
Паттерны проектирования: абстрактная фабрика, фабричный метод, прототип;
evvcom (2006-08-10 13:31:00) [9]> создавайте объекты косвенно.
Как это? Что за понятие?
Kolan (2006-08-10 13:11:00) [10]
> В этом случае нарушается принцип полиморфизма и у потомка
> должен быть явно вызван этот метод
Не это я увидел.
Просто нашел объяснение почему так делать не надо, сразу ту ветку вспомнил. А тут случай выдался.. и другим это рассказать(хотя мож все этои так знают ) :)
Пусик (2006-08-10 13:06:00) [11]
> Kolan © (10.08.06 12:45) [13]
см. [8].
Не должно, но может. В этом случае нарушается принцип полиморфизма и у потомка должен быть явно вызван этот метод.
PS.
Я знаю, что Земля не круглая, и в Черном море вода не черная.
Kolan (2006-08-10 12:45:00) [12]
> Пусик © (10.08.06 09:50) [8]
Опять вы за свое :)
Кстати как-то вы мне это уже показывали и я тогда привел пример про виртуальные методы. Что то вроде:
Пример виртуальной функции в Delphi
Язык Delphi тоже поддерживает полиморфизм. Рассмотрим пример:
Объявим два класса. Предка(Ancestor):
TAncestor = class
private
protected
public
{Виртуальная процедура.}
procedure VirtualProcedure; virtual;
procedure StaticProcedure;
end;
и его потомка (Descendant):
TDescendant = class(TAncestor)
private
protected
public
{Перекрытие виртуальной процедуры.}
procedure VirtualProcdure; override;
procedure StaticProcedure;
end;
Как видно в классе предке объявлена виртуальная функция - VirtualProcdure. Чтобы воспользоваться достоинствами полиморфизма её нужно перекрыть в потомке.
Реализация выглядит следующим образом:
{ TAncestor }
procedure TAncestor.StaticProcedure;
begin
ShowMessage('Ancestor static procedure.');
end;
procedure TAncestor.VirtualProcdure;
begin
ShowMessage('Ancestor virtual procedure.');
end;
{ TDescendant }
procedure TDescendant.StaticProcedure;
begin
ShowMessage('Descendant static procedure.');
end;
procedure TDescendant.VirtualProcdure;
begin
ShowMessage('Descendant override procedure.');
end;
Посмотрим как это работает:
procedure TForm2.BitBtn1Click(Sender: TObject);
var
MyObject1: TAncestor;
MyObject2: TAncestor;
begin
MyObject1 := TAncestor.Create;
MyObject2 := TDescendant.Create;
try
MyObject1.StaticProcedure;
MyObject1.VirtualProcdure;
MyObject2.StaticProcedure;
MyObject2.VirtualProcdure;
finally
MyObject1.Free;
MyObject2.Free;
end;
end;
Дык вот а вы говорили что зачем нужно объявлять так:
MyObject1: TAncestor;
MyObject2: TAncestor;
И мол почему бы не объявить сразу конкретные типы.
Так вот даю вам ответ:
при создании объекта явно указывается класс. Задание имени класса привя¬зывает вас к конкретной реализации, а не к конкретному интерфейсу. Это может осложнить изменение объекта в будущем. Чтобы уйти от такой про¬блемы, создавайте объекты косвенно.
:)
evvcom (2006-08-10 11:50:00) [13]
> [11] DrPass © (10.08.06 10:19)
> Inherited выполняется для любых методов
Для любых методов -процедур. Для методов-функций такое не катит вообще без имени и параметров.
DrPass (2006-08-10 10:19:00) [14]
> Насколько я понимаю, inherited без указания "что-именно-
> inherited" должно бы выполняться только для виртуальных
> методов, у которых список параметров гарантированно совпадает
> со списком параметров предка...
Все верно, кроме слова "виртуальных". Inherited выполняется для любых методов, и никакого фокуса в этом нет - вызов-то формируется еще на этапе компиляции.
Чапаев (2006-08-10 10:10:00) [15]
> if FCanDestroy then inherited Free;
Кстати, вот что меня удивляет... Если "inherited Free" заменить на "inherited", всё равно успешно компилируется и выполняется. Насколько я понимаю, inherited без указания "что-именно-inherited" должно бы выполняться только для виртуальных методов, у которых список параметров гарантированно совпадает со списком параметров предка...
Anatoly Podgoretsky (2006-08-10 09:54:00) [16]Fay © (10.08.06 03:36) [6]
В смысле что не виртуальный
Пусик (2006-08-10 09:50:00) [17]
> Loginov Dmitry © (10.08.06 07:48) [7]
> > В смысле?Он есть только у TObject. У потомков метода Free
> быть не должно. Об этом говорит остутствие директивы virtual
Не должно, но может. В этом случае нарушается принцип полиморфизма и у потомка должен быть явно вызван этот метод. В некоторых случаях такая возможность бывает нужна.
TChild=class(TObject)
FCanDestroy: Boolean;
destructor Destroy; override;
procedure Free;
end;
destructor TChild.Destroy;
begin
ShowMessage('Destroy');
inherited;
end;
procedure TChild.Free;
begin
if FCanDestroy then inherited Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Obj: TChild;
begin
Obj := TChild.Create;
Obj.FCanDestroy := False;
Obj.Free; //Так будет работать, как запланировано(Зависит от FCanDestroy)
TObject(Obj).Free; //А так в любом случае будет вызван деструктор
end;
В этом примере происходит не перекрытие метода Free, а его замещение.
Loginov Dmitry (2006-08-10 07:48:00) [18]> В смысле?
Он есть только у TObject. У потомков метода Free быть не должно. Об этом говорит остутствие директивы virtual
Fay (2006-08-10 03:36:00) [19]2 Anatoly Podgoretsky © (09.08.06 19:53) [5]
> статический метод
В смысле?
Anatoly Podgoretsky (2006-08-09 19:53:00) [20]Free статический метод.
Destroy виртуальный деструктор.