Форум: "Основная";
Текущий архив: 2006.09.24;
Скачать: [xml.tar.bz2];
ВнизЧем отличается в классах Free от Destroy? Найти похожие ветки
← →
Kiloper (2006-08-09 11:34) [0]Чем отличается в классах Free от Destroy? Так и так работает?
← →
Сергей М. © (2006-08-09 11:37) [1]a.Free есть тот же a.Destroy, но с предварительной проверкой переменной a на nil
← →
Kiloper (2006-08-09 11:39) [2]спасибо
← →
DrPass © (2006-08-09 11:56) [3]
> Чем отличается в классах Free от Destroy?
Удерживая клавишу Ctrl, щелкаешь на вызов Free в тексте программы. Очень полезный способ познания
← →
Desdechado © (2006-08-09 13:00) [4]Деструктор напрямую вызывать не рекомендуется. Free - это обертка для него...
← →
Anatoly Podgoretsky © (2006-08-09 19:53) [5]Free статический метод.
Destroy виртуальный деструктор.
← →
Fay © (2006-08-10 03:36) [6]2 Anatoly Podgoretsky © (09.08.06 19:53) [5]
> статический метод
В смысле?
← →
Loginov Dmitry © (2006-08-10 07:48) [7]> В смысле?
Он есть только у TObject. У потомков метода Free быть не должно. Об этом говорит остутствие директивы virtual
← →
Пусик © (2006-08-10 09:50) [8]
> 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, а его замещение.
← →
Anatoly Podgoretsky © (2006-08-10 09:54) [9]Fay © (10.08.06 03:36) [6]
В смысле что не виртуальный
← →
Чапаев © (2006-08-10 10:10) [10]
> if FCanDestroy then inherited Free;
Кстати, вот что меня удивляет... Если "inherited Free" заменить на "inherited", всё равно успешно компилируется и выполняется. Насколько я понимаю, inherited без указания "что-именно-inherited" должно бы выполняться только для виртуальных методов, у которых список параметров гарантированно совпадает со списком параметров предка...
← →
DrPass © (2006-08-10 10:19) [11]
> Насколько я понимаю, inherited без указания "что-именно-
> inherited" должно бы выполняться только для виртуальных
> методов, у которых список параметров гарантированно совпадает
> со списком параметров предка...
Все верно, кроме слова "виртуальных". Inherited выполняется для любых методов, и никакого фокуса в этом нет - вызов-то формируется еще на этапе компиляции.
← →
evvcom © (2006-08-10 11:50) [12]
> [11] DrPass © (10.08.06 10:19)
> Inherited выполняется для любых методов
Для любых методов-процедур. Для методов-функций такое не катит вообще без имени и параметров.
← →
Kolan © (2006-08-10 12:45) [13]
> Пусик © (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;
И мол почему бы не объявить сразу конкретные типы.
Так вот даю вам ответ:при создании объекта явно указывается класс. Задание имени класса привя¬зывает вас к конкретной реализации, а не к конкретному интерфейсу. Это может осложнить изменение объекта в будущем. Чтобы уйти от такой про¬блемы, создавайте объекты косвенно.
:)
← →
Пусик © (2006-08-10 13:06) [14]
> Kolan © (10.08.06 12:45) [13]
см. [8].
Не должно, но может. В этом случае нарушается принцип полиморфизма и у потомка должен быть явно вызван этот метод.
PS.
Я знаю, что Земля не круглая, и в Черном море вода не черная.
← →
Kolan © (2006-08-10 13:11) [15]
> В этом случае нарушается принцип полиморфизма и у потомка
> должен быть явно вызван этот метод
Не это я увидел.
Просто нашел объяснение почему так делать не надо, сразу ту ветку вспомнил. А тут случай выдался.. и другим это рассказать(хотя мож все этои так знают ) :)
← →
evvcom © (2006-08-10 13:31) [16]> создавайте объекты косвенно.
Как это? Что за понятие?
← →
Kolan © (2006-08-10 13:33) [17]
> Как это? Что за понятие?
Продолжение цитаты:Паттерны проектирования: абстрактная фабрика, фабричный метод, прототип;
← →
Kolan © (2006-08-10 13:41) [18]Те не надо обявлять конктреные типы как например тут:
> 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:42) [19]
> инстанцировать конктретные экземпляры
инстанцировать экземпляры конкретных классов.
← →
evvcom © (2006-08-10 13:50) [20]> [18] Kolan © (10.08.06 13:41)
Но я бы не назвал это косвенным созданием.
В твоем примере аргумент, что надо заменить по тексту имя класса в одном или 2-х местах, это не аргумент. Вот если бы ты сказал, что не нужно будет совсем править чужой код (который в данном случае становится генофондом, а про генофонд, надеюсь, уже все знают), вот это аргумент.
← →
Kolan © (2006-08-10 13:52) [21]Ну это я так себе это понял. Мож и не верно.
Тут смотри:Виртуальный конструктор Create класса TComponent
http://delphimaster.net/view/1-1154509872/
← →
Kolan © (2006-08-10 14:07) [22]Перечитал
> который в данном случае становится генофондом, а про генофонд,
> надеюсь, уже все знают
Что становится генофондом?
← →
evvcom © (2006-08-10 14:08) [23]> [21] Kolan © (10.08.06 13:52)
Да там особо и смотреть нечего. Ты DevExpress (dxGrid, dxTreeList) по возможности посмотри и попробуй написать и зарегить свои классы столбцов. Вот там есть чему поучиться, настолько гибко написано. Да такое, наверняка, и в других продвинутых библиотеках найдешь.
← →
evvcom © (2006-08-10 14:13) [24]> [22] Kolan © (10.08.06 14:07)
> Что становится генофондом?
Код, библиотека, которые в общем-то уже предназначены для использования в прикладных целях.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.09.24;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.544 c