Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как создать функцию возвращающею разные типы? [D5, Win95/98, Win2k, WinXP]


Страницы:   1 2

Erik1 ©   (2004-09-23 16:39:00) 

Я пробовал создать базовый клас и от него унаследовать 2 потомков в которых переопределить нужную функцию. Но будет ли это работать?
Базовый клас:
 TActivItem = class
 private
   fItem: TObject;
   fStart: TSystemTime;
   fStatus: TReportStatus;
 protected
   fID: integer;
   fDescription: string;
   function  GetItem: TObject; dynamic; abstract; //Общая функция
 public
   constructor Create(Value: TObject);
   destructor Destroy; override;
   procedure Cancel; dynamic; abstract;
 end;
Потомок:
 TVisThread = class(TActivItem)
 protected
   function  GetItem: TCustomThread; overload;
 public
   procedure Cancel; override;
   property Item: TCustomThread read GetItem;
 end;
Второй потомок:
 TVisReport = class(TActivItem)
 private
   fReportItem: TReportItem;
   ..........
 protected
   function  GetItem: TBaseReport; overload; //override;
 public
   property Item: TBaseReport read GetItem;
 end;
И использование:
TReportManager = class(TComponent)
......
public
 property  Items[Index: Integer]: TActivItem read GetItems write     SetItems; default;
end;
В Items записываю нужный клас и всегда могу вызывать общие методы  определеные в TActivItem. Насколько это правильно?


Rem   (2004-09-23 18:28:00) [1]

1. Варианты не работают с классами.
2. Используйте overloaded/abstract/overriden/ метод с var-параметрами.


Sandman25   (2004-09-23 17:58:00) [2]

[30] Defunct ©   (23.09.04 17:55)

Лучше учесть [29] Sandman25 ©   (23.09.04 17:52)
И написать

Procedure TReportManager.Execute(Item: ...);
Begin
 if Item.RequiresNewThread then
 begin
   ...// создаем новый Thread
   Item.Execute
   ...
 end
 else
   Item.Execute
End;

Хотя на самом деле новый поток должен создаваться самим TVisReport в его DoStart :)


Defunct   (2004-09-23 17:55:00) [3]

Erik1 ©   (23.09.04 17:49) [28]

> меня TVisReport привелигированый класс, он выполняется подругому чем остальные.

берем пример Sandman25 ©   (23.09.04 17:41) [27]

изменяем реализацию Execute:

Procedure TReportManager.Execute;
Begin
 If Item is TVisReport Then
 Begin
   PrepareToCreatePriviligedReport;
   CreateAnExtendedReportThread;
 End Else
 If Item is ... Then
 Begin
   DoStart;
   DoExecute;
   DoFinish;  
 End и т.д.
End;


Sandman25   (2004-09-23 17:52:00) [4]

[28] Erik1 ©   (23.09.04 17:49)

Добавляете метод function RequiresNewThread: Boolean.
Сам Thread или Report не меняется, в этом и есть смысл ввода Адаптеров.


Erik1   (2004-09-23 17:49:00) [5]

У меня TVisReport привелигированый класс, он выполняется подругому чем остальные. Для него report manager предоставляет свой тред для его выполнения, а остальным кукиш, приходится самим крутится. Интерфейс для управления хочется иметь общий. Ктоме того все треды от базового пронаследованы. Кащется есть 2 идеии: оставить все как есть и запытать в работе или реорганизовать и переложить обработку тредов на на обертки TVis...


Sandman25   (2004-09-23 17:41:00) [6]

TVis = class
 protected
   procedure DoStart; virtual; abstract;
   procedure DoExecute; virtual; abstract;
   procedure DoFinish; virtual; abstract;
 ...
 public
   procedure Execute;
 end;

procedure TVis.Execute;
begin
 DoStart;
 DoExecute;
 DoFinish;
end;


TVisThread = class(TActivItem)
protected
  procedure DoStart; override;
  procedure DoExecute; override;
  procedure DoFinish; override;
end;
 ...

Manager:
 Item[15].Execute;


Defunct   (2004-09-23 17:37:00) [7]

Sandman25 ©   (23.09.04 17:18) [16]

Да.. пардон забыл о мелочи... ;)
is/as таки нужно применять перед вызовом у меня это было спрятано в статическом приватном методе, как-то и не задумывался..

Erik1 ©   (23.09.04 17:27) [20]
сорри, за то что не смог помочь, нормально написать пример тоже нужно время..


Sandman25   (2004-09-23 17:37:00) [8]

[23] Erik1 ©   (23.09.04 17:29)

Как оболочка они не должны различаться в interface-секции. Только реализация разная. И у них у всех должны быть virtual методы типа DoFinish и т.д.


Erik1   (2004-09-23 17:36:00) [9]

to Sandman25
Говорит, чисто теоритически, ни разу неиспользовал. И как это реализавать в конкретном коде незнаю.


Erik1   (2004-09-23 17:29:00) [10]

to Sandman25
А для чего я по твоему написал TVisThread и TVisReport они и есть обольчка. :)


Sandman25   (2004-09-23 17:29:00) [11]

Erik1

Если Вам что-то говорит фраза "паттерн Адаптер", то ИМХО это именно он.


Sandman25   (2004-09-23 17:27:00) [12]

[18] Erik1 ©   (23.09.04 17:20)

Как он может запустить объект, если он не знает его тип. Либо через интерфейсы, либо пусть вызывает фабричную процедуру, которая лежит в отдельном модуле и которую надо будет изменять каждый раз.
ИМХО лучше написать оболочку - класс, который будет выполнять роль интерфейса. То есть разные наследники данного класса будут уметь запускать разные объекты, хранящиеся в них же.


Erik1   (2004-09-23 17:27:00) [13]

to Defunct
Понимаеш TVisThread и TVisReport это просто обертка над уже реализоваными классами. И они ничего незнают о том, что надо наследоватся от общего предка. У меня неальный проекет в котором я переписываю Report manager. Так, что твой способ неподойдет.


Sandman25   (2004-09-23 17:23:00) [14]

type
 TAbstractFamily1 = class
   function GetItem: TAbstractFamily1; virtual; abstract;
 end;

 TClass1Family1 = class(TAbstractFamily1)
   function GetItem: TAbstractFamily1; override;
 end;

 TAbstractFamily2 = class(TAbstractFamily1)
   function GetItem: TAbstractFamily2; reintroduce; virtual; abstract;
 end;

 TClass1Family2 = class(TAbstractFamily2)
   function GetItem: TAbstractFamily2; override;
 end;

procedure TForm1.FormCreate(Sender: TObject);
var
 Object2                     : TAbstractFamily1;
begin
 Object2 := TClass1Family2.Create;
 try
   Object2.GetItem;
 finally
   Object2.Free;
 end;
end;

{ TClass1Family1 }

function TClass1Family1.GetItem: TAbstractFamily1;
begin
 ShowMessage('1');
end;

{ TClass1Family2 }

function TClass1Family2.GetItem: TAbstractFamily2;
begin
 ShowMessage('1');
end;

При запуске получаю AbstractError


Erik1   (2004-09-23 17:20:00) [15]

to Sandman25
А если у меня добавится новый клас то я сразу должен исходники переписывать? У меня есть TReportManager он неполностью знает с чем работает. Но должен уметь запустить объект и остановить его, кроме того уведомлять о произошедших событиях. Вобщем проектирую я его сейчас, если будут другии идеии то с удовольствием расмотрю. Можно конечно мойти через интерфейсы, этот вариант я еше необдумывал.


Defunct   (2004-09-23 17:19:00) [16]

[15]
Блин, сам запутался в этих единичках и двоечках...

Object1, Object2 : TAbstractFamily 1;

Object1 := TClass1Family 2.Create;
Object2 := TClass1Family 1.Create;

Object1.GetItem вернет TAbstractFamily 2;
Object2.GetItem вернет TAbstractFamily 1;


Sandman25   (2004-09-23 17:18:00) [17]

В классе TClass1Family2 метод TAbstractFamily1.GetItem остался абстрактным.
На каком основании TClassFamily.GetItem привязывается к нему? Ведь Вы же явно указали (reintroduce), что методы не имеют ничего общего.


Defunct   (2004-09-23 17:16:00) [18]

Erik1 ©   (23.09.04 17:02) [11]

Я немного поправлю [7], а то там написал не совсем доступно для понимания:

TAbstractFamily 1= class
Private
..
Function GetItem:TAbstractFamily 1; virtual;abstract;
..
End;

TClass1Family1 = class(TAbstractFamily 1)
Function GetItem:TAbstractFamily 1; override;
End;

..

TAbstractFamily2 = class(TAbstractFamily1)
Function GetItem:TAbstractFamily2; reintroduce; virtual; abstract;
End;

TClass1Family2 = class(TAbstractFamily2)
Function GetItem:TAbstractFamily2; override;
End;


Object1, Object2 :AbstractFamily1;

Object1 := TClass1Family2.Create;
Object2 := TClass1Family2.Create;

Object1.GetItem вернет TAbstractFamily2;
Object2.GetItem вернет TAbstractFamily1;


Sandman25   (2004-09-23 17:10:00) [19]

[12] Defunct ©   (23.09.04 17:08)

Нет. Будет AbstractError.


Sandman25   (2004-09-23 17:08:00) [20]

[11] Erik1 ©   (23.09.04 17:02)

Вопрос. Зачем называть GetItem, если можно назвать GetThread?
Как планируется вызывать GetItem? Ведь тип объекта уже явно будет известен, см. пост by Digitman


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо