Проверьте имя класса - PullRequest
       11

Проверьте имя класса

4 голосов
/ 09 февраля 2009

Я не знаю имя класса объекта OWNER. Поэтому я должен везде проверять свои коды следующим образом:

if TObject(OWNER) is TFirstClass then begin
  TFirstClass(OWNER).FirstFunction;
  TFirstClass(OWNER).SecondFunction;
  ...
end else
if TObject(OWNER) is TSecondClass then begin
  TSecondClass(OWNER).FirstFunction;
  TSecondClass(OWNER).SecondFunction;
  ...
end;

Есть ли лучший способ? Потому что я должен сделать это, если условие во многих местах кодов. Все функции TFirstClass и TSecondClass (которые мне нужно запустить) одинаковы.

Примечание: я использую Delphi 5.

Ответы [ 3 ]

12 голосов
/ 09 февраля 2009

Если у вас нет доступа к TFirstClass и TSecondClass, но вы все еще хотите упростить свой код, вот способ:

Создание базового класса адаптера:

type
  TMyAdapter = class(TObject)
  public
    procedure FirstMethod; virtual; abstract;
    procedure SecondMethod; virtual; abstract;
  end;

Затем создайте классы-потомки TFirstClassAdapter и TSecondClassAdapter и дайте им каждому частную ссылку на экземпляр TFirstClass или TSecondClass соответственно. Добавьте конструктор, который устанавливает эту ссылку. Переопределите методы классов адаптера, чтобы они вызывали адаптированные классы.

type
  TFirstClassAdapter = class(TMyAdapter)
  private
    fObject: TFirstClass;
  public
    constructor Create(AAdaptedObject: TFirstClass);

    procedure FirstMethod; override;
    procedure SecondMethod; override;
  end;

constructor TFirstClassAdapter.Create(AAdaptedObject: TFirstClass);
begin
  inherited Create;
  fObject := AAdaptedObject;
end;

procedure TFirstClassAdapter.FirstMethod;
begin
  fObject.FirstMethod;
end;

procedure TFirstClassAdapter.SecondMethod;
begin
  fObject.SecondMethod;
end;

То же самое для другого класса. Теперь вам нужно только решить, создадите ли вы адаптер один раз и передадите его, или создадите функцию, которую вы вызываете везде, где вам это нужно, и которая даст вам адаптер для вашего конкретного класса.

Если вы реализуете адаптер с использованием интерфейсов, вам даже не нужно будет управлять временем жизни адаптера самостоятельно.

Таким образом, вы можете получить полиморфное поведение, которое Ульрих дал в своем ответе , но без необходимости менять TFirstClass и TSecondClass.

11 голосов
/ 09 февраля 2009

Производные TFirstClass и TSecondClass из общего базового класса, который объявляет виртуальные методы FirstFunction и SecondFunction.

Ули.

0 голосов
/ 10 февраля 2009

Сначала простите за мой плохой английский.
Если вы не можете сделать ответы до 2 (Адаптеры и производные от базового класса), вы можете использовать RTTI для доступа к процедуре по ее имени.

Процедура должна быть объявлена ​​в опубликованном разделе.

Если у вас есть такая декларация:

  TFirstClass = class(TObject)
  published
    procedure FirstFunction;
    procedure SecondFunction;
  end;
  TSecondClass = class(TObject)
  published
    procedure FirstFunction;
    procedure SecondFunction;
  end

Вы можете сделать что-то подобное, чтобы выполнить метод, если у вас есть имя:

  // Acceso a la rutina; TObject is a Base class for 
  // TFirstClass and TSecondClass
  Routine.Data := Pointer(obj as TObject);
  // Devuelve la dirección de un método published; Method for it's name
  Routine.Code := (obj as TObject).MethodAddress('SecondFunction');
  // Not find
  if (Routine.Code = nil) then Exit;
  // execute
  TExecuteMethod(Routine);

Подобные коды вы можете увидеть здесь:
* Tip4 * Tip7

Привет.

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