Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.10.23;
Скачать: [xml.tar.bz2];

Вниз

Как изменить тип создоваемого объекта в методе предка.   Найти похожие ветки 

 
Kolan ©   (2005-09-26 16:02) [0]

Здравствуйте,
 Есть у меня стек:
TStack = class(TCustomList)
 private
 protected
 public
   function GetListAsString: string; override;
   function GetListAsStrings: TStrings; override;
   function Add(Data: TNodeData): Boolean; override;
   function Extract: TNodeData; override;
   constructor Create(FormHandle: THandle); override;
   destructor Destroy; override;
 end;

Вот его метод Add

function TStack.Add(Data: TNodeData): Boolean;
var
 Node: TCustomNode;
begin
 inherited Add(Data);
 Node := TCustomNode.Create;
 try
   Node.Data := Data;
   if Head <> nil then
     Node.FNext := Head;
   Head := Node;
   Result := True;
 except
   Result := False;
 end;    
end;


Теперь я хочу сделать такойже стек но элементы которого будут иметь две ссылки:

TDoubleTreeNode = class(TCustomNode)
 private
   FParent: TDoubleTreeNode;
 protected
 public
   constructor Create; override;
   destructor Destroy; override;
 end;


Как написать наследника от стека, поддерживающего элементы типа TDoubleTreeNode

Неужели для того, чтобы изменить
Node := TCustomNode.Create;
на
Node := TDoubleTreeNode.Create;
Придётся переписать весь код метода Add. (Переписать я его смогу ессесно, интересно узнать как правильно спроектировать классы.)


 
Kolan ©   (2005-09-26 17:18) [1]

Блин опять похоже никто не понял ничего
Я имею в виду что в предке будет

function TStack.Add(Data: TNodeData): Boolean;
var
Node: TCustomNode;
begin
inherited Add(Data);
Node := TCustomNode.Create;
try
  Node.Data := Data;
  if Head <> nil then
    Node.FNext := Head;
  Head := Node;
  Result := True;
except
  Result := False;
end;    
end;


А в потомке

function TStack.Add(Data: TNodeData): Boolean;
var
Node: TCustomNode;
begin
inherited Add(Data);
Node := TDoubleTreeNode.Create;
try
  Node.Data := Data;
  if Head <> nil then
    Node.FNext := Head;
  Head := Node;
  Result := True;
except
  Result := False;
end;    
end;

Это если переписать. Я вно я гдето ошибся. Как сделать так чтобы можно было
в качестве эл списка создавать  любого потомка TCustomNode

Может
inherited Add
а потом
преобразовать node из TCustomNode в TDoubleTreeNode
Только как???


 
jack128 ©   (2005-09-26 17:30) [2]

TStack = class(TCustomList)
private
protected
 function CreateNode: TCustomNode; virtual;
public
  function GetListAsString: string; override;
  function GetListAsStrings: TStrings; override;
  function Add(Data: TNodeData): Boolean; override;
  function Extract: TNodeData; override;
  constructor Create(FormHandle: THandle); override;
  destructor Destroy; override;
end;

TStack2 = class(TStack)
protected
 function CreateNode: TCustomNode; override;
end;

function TStack.CreateNode: TCustomNode;
begin
 Result := TCustomNode.Create;
end;

function TStack.Add(Data: TNodeData): Boolean;
var
Node: TCustomNode;
begin
inherited Add(Data);
Node := CreateNode;
try
 Node.Data := Data;
 if Head <> nil then
   Node.FNext := Head;
 Head := Node;
 Result := True;
except
 Result := False;
end;    
end;

function TStack2.CreateNode: TCustomNode;
begin
 Result := TDoubleTreeNode.Create;
end;


 
jack128 ©   (2005-09-26 17:34) [3]

Или можно сделать событие OnCreateNode в котором создовать нужный узел. Тогда не придется для каждого наследника TCustomNode создовать наследника TStack. Либо, если TCustomNode имеет виртуальный конструктор, то можно создать свойство NodeClass: TCustomNodeClass; тогда даже обработчик события не нужно будет писать.  Но при прочих равных, я предпочитаю вариант из поста [2]


 
umbra ©   (2005-09-26 19:16) [4]

Можно


TCustomListNode = class of TCustomNode;

TStack = class(TCustomList)
private
protected
function CreateNode: TCustomNode; virtual;
public
 function GetListAsString: string; override;
 function GetListAsStrings: TStrings; override;
 function Add(Node: TCustomNodeClass; Data: TNodeData): Boolean; override;
 function Extract: TNodeData; override;
 constructor Create(FormHandle: THandle); override;
 destructor Destroy; override;
end;

function TStack.Add(ANode: TCustomNodeClass; Data: TNodeData): Boolean;
var
Node: TCustomNode;
begin
inherited Add(Data);
Node := ANode.Create;
try
 Node.Data := Data;
 if Head <> nil then
   Node.FNext := Head;
 Head := Node;
 Result := True;
except
 Result := False;
end;    
end;


 
Kolan ©   (2005-09-26 20:44) [5]

jack128 ©   (26.09.05 17:34) [3]
Понял, большой Сенкс :)

umbra ©   (26.09.05 19:16) [4]
OK, но воспользуюсь [2]


 
Kolan ©   (2005-09-26 21:27) [6]

Ещё один вопрос. Сразу не учёл...
 При добавлении в стек с "двойными" элементами мне надо присовоить значение FParent поэтому метод Add выглядит так:
function Add(Data: TNodeData; ParentNode: TCustomNode): Boolean;
Осюда 3 вопроса

1. Как правильно это описать? После прочтения справки думаю что так: В предке
function Add(Data: TNodeData): Boolean; overload; override;
а в потомке
function Add(Data: TNodeData; ParentNode: TCustomNode): Boolean; reintroduce; overload;
Но не уверен, а компилируется и без overload; и без reintroduce;.

2. :))) Как теперь использовать код наследника. Сделал как советовал, теперь выглядит так: jack128 ©
function TStack.Add(Data: TNodeData): Boolean;
var
 Node: TCustomNode;
begin
 inherited Add(Data);
 Node := CreateNode;
 try
   Node.Data := Data;
   if Head <> nil then
     Node.FNext := Head;
   Head := Node;
   Result := True;
 except
   Result := False;
 end;
end;


3. Как присвоить переданный ParentNode. Т.е.:
Так
(1)var
 P: TCustomNode;
begin
 P := ParentNode;
(ParentNode ведь создан не как TCustomNode)
или так
(2)
P := (ParentNode as TDoubleTreeNode);

Я думаю что правильно (1), вроде по идее указатель и в африке указатель...

----
С уважением, Kolan


 
Kolan ©   (2005-09-26 22:23) [7]

Решил заодно и список сделать дву связным. Поэтому сделал его потом ком не стека а очереди
TDoubleTreeList = class(TQueue)
 private
 protected
   function CreateNode: TCustomNode; override;
 public
   function Add(Data: TNodeData; ParentNode: TCustomNode): Boolean; reintroduce; overload;
 end;


А элемент выглядит так:
TDoubleTreeNode = class(TCustomNode)
 private
   FPrevious: TDoubleTreeNode;
   FParent: TDoubleTreeNode;
 protected
 public
   constructor Create; override;
   destructor Destroy; override;
   property Parent: TDoubleTreeNode read FParent write FParent;
   property Previous: TDoubleTreeNode read FPrevious write FPrevious;
 end;

Добавилась ссылка на предыдущий.

Тк в очереди Add добовляет  конец
var
 Node: TCustomNode;
begin
 inherited Add(Data);
 Node := CreateNode;
 try
   Node.Data := Data;
   if Head <> nil then
     Node.FNext := Head
   else
     Tail := Node;
   Head := Node;
   Result := True;
 except
    Result := False;
 end;
end;


У нового двухсвязного списка сделал Add так
function TDoubleTreeList.Add(Data: TNodeData;
 ParentNode: TCustomNode): Boolean;
begin
 inherited Add(Data);
 (Head as TDoubleTreeNode).FParent := (ParentNode as TDoubleTreeNode);
 if Head.Next <> nil then
   (Head as TDoubleTreeNode).Previous := (Head as TDoubleTreeNode);
end;


Жду ШО я сделал не так :)))


 
Kolan ©   (2005-09-27 21:20) [8]

up


 
jack128 ©   (2005-09-27 21:44) [9]

Kolan ©   (26.09.05 21:27) [6]
1. Как правильно это описать? После прочтения справки думаю что так: В предке
function Add(Data: TNodeData): Boolean; overload; override;
а в потомке
function Add(Data: TNodeData; ParentNode: TCustomNode): Boolean; reintroduce; overload;


зачем?? В предке function Add(Data: TNodeData): Boolean; а в наследнике function Add(Data: TNodeData; ParentNode: TCustomNode): Boolean; причем метод потомка описать так

Kolan ©   (26.09.05 22:23) [7]
Решил заодно и список сделать дву связным. Поэтому сделал его потом ком не стека а очереди

как всязаны двухсвязность или односвязность списка и стек или очередь??  Это понятия параллельные друг другу..
Kolan ©   (26.09.05 22:23) [7]
Добавилась ссылка на предыдущий.

а на предыдущий где?

Kolan ©   (26.09.05 22:23) [7]
TDoubleTreeNode = class(TCustomNode)
private
  FPrevious: TDoubleTreeNode;
  FParent: TDoubleTreeNode;
protected
public
  constructor Create; override;
  destructor Destroy; override;
  property Parent: TDoubleTreeNode read FParent write FParent;
  property Previous: TDoubleTreeNode read FPrevious write FPrevious;
end;

весело. так почему же ты объявил TDoubleTreeList.function Add(Data: TNodeData; ParentNode: TCustomNode): Boolean; если у тебя TDoubleTreeNode = class(TCustomNode)
private
  FPrevious: TDoubleTreeNode;
  FParent: TDoubleTreeNode;  ?  

еще как сие
Kolan ©   (26.09.05 22:23) [7]
Тк в очереди Add добовляет  конец

вяжется в этим кодом

var
Node: TCustomNode;
begin
inherited Add(Data);
Node := CreateNode;
try
  Node.Data := Data;
  if Head <> nil then
    Node.FNext := Head
  else
    Tail := Node;
  Head := Node; // безусловно помещает узел в НАЧАЛО списка


 
jack128 ©   (2005-09-27 21:46) [10]

jack128 ©   (27.09.05 21:44) [9]
Kolan ©   (26.09.05 22:23) [7]
Добавилась ссылка на предыдущий.
а на предыдущий где?

В смысле, а где ссылка на СЛЕДУЮЩИЙ элемент


 
Kolan ©   (2005-09-27 22:22) [11]

зачем?? В предке function Add(Data: TNodeData): Boolean; а в наследнике function Add(Data: TNodeData; ParentNode: TCustomNode): Boolean; причем метод потомка описать так

как всязаны двухсвязность или односвязность списка и стек или очередь??  Это понятия параллельные друг другу..

Это я просто чтобы вы знали, а то в начале один предок потом другой просто информация короче :)

весело. так почему же т...

Понятно поправлю..

В смысле, а где ссылка на СЛЕДУЮЩИЙ элемент

В предке:
TCustomNode = class
 private
   FData: TNodeData;
   FNext: TCustomNode;
 protected

 public
   procedure FillNode(Data: TNodeData; Next: Pointer);
   constructor Create;
   destructor Destroy; override;
   property Data: TNodeData read FData write FData;
   property Next: TCustomNode read FNext write FNext;
 published

 end;


безусловно помещает узел в НАЧАЛО списка
Да это и имелось в виду описка...


 
Игорь Шевченко ©   (2005-09-28 01:01) [12]

А почему бы у TCustomNode не сделать виртуальный метод AfterInsert, к примеру, передвать туда в качестве параметров Stack и еще что-то необходимое и пусть каждый наследник TCustomNode устанавливает в этом перекрытом методе сам все, что ему нужно...


 
Kolan ©   (2005-09-29 11:53) [13]

Игорь Шевченко ©   (28.09.05 01:01) [12]
Попробую.  

К суботе закончить планирую. Мож ещё чего-нибудь спрошу...
Благодарю за помощь  :)


 
Kolan ©   (2005-09-29 19:50) [14]

Ещё странная странность.
Есть переменная List
var
 MainForm: TMainForm;
 List: TCustomList;


Создан он как TStack

Если его уничтожить так:
 List.Free;
То после проверки на nil вызывается Destroy TObject"a
А если так:
 List.Destroy;
То всё нормально вызывается деструктор TStack

Код TCustomList мож понадобится.

TCustomList = class(TObject)
 private
   FCount: Integer;
   FHead: TCustomNode;
   FFormHandle: THandle;
 protected
 public
   function Add(Data: TNodeData): Boolean; overload; virtual;
   function Extract: TNodeData; virtual;
   function GetListAsString: string; virtual; abstract;
   procedure GetListAsStrings(var Strings: TStrings); virtual; abstract;
   constructor Create(FormHandle: THandle); virtual;
   destructor Destroy; virtual;
   property Count: Integer read FCount;
   property Head: TCustomNode read FHead write FHead;
   property FormaHandle: THandle read FFormHandle;
 end;


 
unknown   (2005-09-29 19:54) [15]

ибо destructor Destroy; virtual; вероятно )


 
Kolan ©   (2005-09-29 20:16) [16]

Объясни если можешь почему так происходит.


 
Игорь Шевченко ©   (2005-09-29 20:34) [17]


>   destructor Destroy; virtual;


destructor Destroy; override;


 
Kolan ©   (2005-09-29 20:59) [18]

Игорь Шевченко ©   (29.09.05 20:34) [17]
Извените за настойчивость, но непойму
1. Почему так вышло(словами).
2. destructor Destroy; override; это к чему ототносится?

Или ссылку с примерами для тупых.
Справку читал, Тайскейру читал.. мож плохо? :)


 
Игорь Шевченко ©   (2005-09-29 21:54) [19]


> Если его уничтожить так:
>  List.Free;
> То после проверки на nil вызывается Destroy TObject"a
> А если так:
>  List.Destroy;
> То всё нормально вызывается деструктор TStack


Потому что TObject.Free вызывает виртуальный деструктор TObject. Для того, чтобы вызывать деструктор твоего объекта, он должен быть объявлен с директивой override.


> 2. destructor Destroy; override; это к чему ототносится?
>  


К твоему классу. Тебе надо так объявить вместо destructor Destroy; virtual;
А сейчас ты своим объявлением добился того, что у твоего объекта два деструктора - один унаследованный от TObject, а второй привнесен тобой самим. При этом унаследованный деструктор виден только при приведении типа твоего объекта к TObject и больше нигде.

Кроме того, тебе нужно включить в опциях проекта на закладке Compiler флажки Show hints и Show warnings и писать программу так, чтобы с включенными флажками компилятор не сделал тебе ни одного замечания.
Только после этого задавать вопрос на форуме.


 
Kolan ©   (2005-10-01 11:58) [20]

Всё, доделал.
Спасибо за подробные разяснения :).


 
Ling ©   (2005-10-01 12:17) [21]

Мдяя..... с++ шаблоны рулят, причём намного выходя за рамки того, ради чего они были придуманны 8))

ХОЧУ ШАБЛОНЫ В DELPHI!!!!


 
Kolan ©   (2005-10-01 12:33) [22]

Ling ©   (01.10.05 12:17) [21]
А что такое шаблоны? Ты не про <Ctrl> + J случано...


 
TUser ©   (2005-10-01 12:44) [23]

Имхо, это все решается объявлением
TNodeClass = class of (TCustomNode);
Пример есть в справке.

> ХОЧУ ШАБЛОНЫ В DELPHI!!!!

Возможно, если отказаться от использования IDE.


 
Игорь Шевченко ©   (2005-10-03 12:01) [24]

TUser ©   (01.10.05 12:44) [23]


> > ХОЧУ ШАБЛОНЫ В DELPHI!!!!
>
> Возможно, если отказаться от использования IDE.


С этого места подробнее - как возможно и чем мешает IDE ?


 
Deka ©   (2005-10-03 15:37) [25]

Где-то я читал статью про шаблоны в Дельфи... Кажись в Королевстве Дельфи. Там у автора все замечательно получилось!



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

Форум: "Основная";
Текущий архив: 2005.10.23;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.03 c
11-1108772659
Lars
2005-02-19 03:24
2005.10.23
MultiLine edit box Horizontal Scroll bar


1-1127974527
Ascan
2005-09-29 10:15
2005.10.23
Символ сортировки на Title колонки Grid


14-1128069428
LordOfRock
2005-09-30 12:37
2005.10.23
Вот, оказывается, как это хорошо звучит!


2-1127841557
userrrrr
2005-09-27 21:19
2005.10.23
Как програмно изменит: Свойства обозревателя?


6-1117099451
PalPalych
2005-05-26 13:24
2005.10.23
Проверка наличия подключения к Инету





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский