Приведение из TObject к типу интерфейса - PullRequest
2 голосов
/ 06 августа 2009

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

function TNodeFactory <T>.CreateNode (ID : Integer) : INodeInterface <T>;
var
  NodeClass : TClass;
begin
  NodeClass := FindRegisteredClass (ID);
  Result := NodeClass.Create;      
end;

Это приводит к ошибке компилятора:

E2010 Incompatible Types: 'INodeInterface<TNodeFactory<T>.T>' and 'TObject'

Приведение не работает тоже.

Что мне здесь не хватает?

РЕДАКТИРОВАТЬ: Текущая реализация

TNodeFactory <T> = class
private
  type
    TRegisteredNodeType = record
      ID : Integer;
      NodeClass : TClass;
    end;
private
  FNodeTypeList : TList <TRegisteredNodeType>
public
  procedure RegisterNodeType (ID : Integer; NodeClass : TClass);
  function  CreateNode (ID : Integer) : INodeInterface <T>;
end;

procedure TNodeFactory <T>.RegisterNodeType (ID : Integer; NodeClass : TClass);
var
  RegisteredType : TRegisteredNodeType;
begin
  RegisteredType.ID := ID;
  RegisteredType.NodeClass := NodeClass;
  FNodeTypeList.Add (RegisteredType);
end;

function TNodeFactory <T>.CreateNode (ID : Integer);
var
  RegisteredType : TRegisteredNodeType;
begin
  for RegisteredType in FNodeTypeList do
    if (RegisteredType.ID = ID) then
      Exit (RegisteredType.NodeClass.Create);
  raise EInvalidNodeType.Create ('No node type with ID ' + IntToStr (ID) + ' registered');
end;

(упрощенные и удаленные проверки ошибок)

Ответы [ 4 ]

3 голосов
/ 06 августа 2009

Проблема в том, что NodeClass является TClass. Если вы создадите NodeClass, это будет просто TObject, а не INodeInterface.

Вы можете попробовать

Result := TInterfacedObject(RegisteredType.NodeClass).Create as INodeInterface

или измените RegisterNodeType на

type
  TInterfacedObjectClass = class of TInterfacedObject;   
...   
procedure RegisteredNodeType...(ID: Integer; NodeClass : TInterfacedObjectClass);

и возврат

Result := RegisteredType.NodeClass.Create as INodeInterface. 
2 голосов
/ 06 августа 2009

Вам нужно использовать функцию Supports (), чтобы извлечь ссылку на интерфейс из объекта. Вы найдете это в SysUtils.

Существует несколько перегруженных версий, вам нужна версия с тремя параметрами, с которой третий параметр «out» возвращает вам ссылку на интерфейс.

2 голосов
/ 06 августа 2009

В Delphi интерфейс не является объектом. И Interface-Pointer не является Objectpointer, поэтому вы не можете их разыграть. Вам необходимо использовать QueryInterface и запросить интерфейс.

function QueryInterface(var IID: TGUID; out Obj: Type):HRESULT

если HRESULT - S_OK, то obj содержит ссылку на запрашиваемый интерфейс.

К сожалению, Delphi (Win32) обрабатывает интерфейсы, отличные от .NET / Java.

0 голосов
/ 06 августа 2009

Позвольте мне начать свой ответ с этого раскрытия: я не настолько знаком с использованием шаблонов в Delphi.

Вы получаете ошибку компилятора, потому что вы пытаетесь вернуть NodeClass, который определен как экземпляр TClass. Однако функция ожидает, что вы вернете экземпляр класса, который реализует INodeInterface. Вы могли бы решить эту проблему с помощью чего-то вроде

Result := INodeInterface(NodeClass.Create);     

или

function TNodeFactory <T>.CreateNode (ID : Integer) : INodeInterface <T>;
var
  NodeClass : TClass;
  NodeInterface: INodeInterface;
begin
  NodeClass := FindRegisteredClass (ID);
  NodeInterface:= NodeClass.Create;
  Result := NodeInterface;      
end;

Возможно, это неправильный ответ, но я надеюсь, что это поможет вам найти решение.

...