delphi中的通用Tlist <imyinterface> </imyinterface>

时间:2014-01-20 15:07:48

标签: delphi interface delphi-xe generic-list

我有一个界面的TList

IImage = interface
// another methods...
  procedure Draw;
end;

在画布中绘制不同的东西。

和父类

TCustomImage = class(TInterfacedObject, IImage)
   procedure Draw; virtual; abstract;
end;

和几个孩子班

TSomeShape = class(TCustomImage, IImage)
   procedure Draw(aCanvas:TCanvas); reintroduce; overload;
end;

TSomeAnotherShape = class(TCustomImage, IImage)
   procedure Draw(aCanvas:TCanvas); reintroduce; overload;
end;

我想编码如下:

var
  list : TList<IImage>;
  shape : IImage;
begin
  try
    list := TList<IImage>.Create;

    list.Add(TSomeShape.Create(atSomePosition));
    list.Add(TSomeAnotherShape.Create(atSomePosition));

    // or better :)
    for shape in list do
      shape.Draw(Canvas); // TSomeShape and TSomeAnotherShape respectively.

  finally
    FreeAndNil(list);
  end;  
end;

UPD
我想将list.Items[I].draw()与正确的类(TSomeShapeTSomeAnotherShape)一起使用。但现在,我发现这个IImage界面是不可能的。我在IImage中有一个方法Draw(Canvas:TCanvas),但认为在类中重新引入方法是可以接受的。

谢谢,我会处理我的代码。 :)

1 个答案:

答案 0 :(得分:3)

问题是您的界面定义不正确。您的具体类使用此签名实现方法:

procedure Draw(Canvas: TCanvas);

但您的界面使用此签名定义了一个方法:

procedure Draw;

您确实需要您的界面和具体实现相匹配。你会想要这样的代码:

type
  IImage = interface
    procedure Draw(Canvas: TCanvas);
  end;

  TCustomImage = class(TInterfacedObject, IImage)
    procedure Draw(Canvas: TCanvas); virtual; abstract;
  end;

  TSomeShape = class(TCustomImage)
    procedure Draw(Canvas: TCanvas); override;
  end;

  TSomeOtherShape = class(TCustomImage)
    procedure Draw(Canvas: TCanvas); override;
  end;

现在一切都匹配,你的代码应该编译得很好,甚至可以做你想要的。


顺便说一句,您的try位置错误。您必须将放在之后才能实例化对象。写

obj := TSomeClass.Create;
try
  // use obj
finally
  obj.Free;
end;

正如您在代码中所拥有的那样,构造函数中的异常将导致finally块运行并尝试在未初始化的引用上调用free。