Приведение объектов Delphi - PullRequest
2 голосов
/ 29 января 2012

У меня есть основной класс и несколько унаследованных классов, которые реализуют метод с тем же именем, например:

MainClass = class(TImage)
  //main class methods...
end;

MyClass1 = class(MainClass)
  procedure DoSomething;
end;

MyClass2 = class(MainClass)
  procedure DoSomething;
end;

MyClass3 = class(MainClass)
  procedure DoSomething;
end;

У меня также есть TList, содержащий указатели на экземпляры объектов (из нескольких классов). Если я хочу вызвать правильную DoSomething процедуру для каждого класса, я использую следующее?

if TList[i] is MyClass1 then
  MyClass1(TList[i]).DoSomething
else if TList[i] is MyClass2 then
  MyClass2(TList[i]).DoSomething
else if TList[i] is MyClass3 then
  MyClass3(TList[i]).DoSomething

Есть ли какой-нибудь метод приведения, который позволяет мне сделать это в нескольких строках кода?

Ответы [ 2 ]

10 голосов
/ 29 января 2012

Да, виртуальный полиморфизм:)

MainClass = class(TImage)
  procedure DoSomething; virtual;
end;

MyClass1 = class(MainClass)
  procedure DoSomething; override;
end;

MyClass2 = class(MainClass)
  procedure DoSomething; override;
end;

MyClass3 = class(MainClass)
  procedure DoSomething; override;
end;

А затем просто:

if TList[i] is MainClass then
  MainClass(TList[i]).DoSomething

Если вы не хотите выполнять пустую процедуру MainClass.DoSomething, вы также можете отметитьэто virtual; abstract;.

4 голосов
/ 29 января 2012

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

  IMainInterface = interface
    ['{0E0624C7-85F5-40AF-ADAC-73B7D79C264E}']
    procedure DoSomething;
  end;

  MyClass = class(TInterfacedObject, IMainInterface)
    procedure DoSomething;
    destructor Destroy; override;
  end;

  MyClass2 = class(TInterfacedObject, IMainInterface)
    procedure DoSomething;
  end;

  MyClass3 = class(TInterfacedObject, IMainInterface)
    procedure DoSomething;
  end;

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

var
  i: integer;
  list: TInterfaceList;
  main: IMainInterface;
begin
  list := TInterfaceList.Create;

  list.Add(MyClass.create);
  list.Add(MyClass2.Create);
  list.Add(MyClass3.Create);

  for i := 0 to 2 do
    if Supports(list[i], IMainInterface, main) then
      main.DoSomething;

  list.Free;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...