2014-01-20 2 views
0

У меня есть TList интерфейса
Generic TList <IMyInterface> в Дельфах

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

, которые привлекают разные вещи в Canvas.

и родительский класс

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() с соответствующими классами (TSomeShape или TSomeAnotherShape). Но теперь я вижу, что это невозможно с этим интерфейсом IImage. У меня был метод Draw(Canvas:TCanvas) в IImage, но я подумал, что приемлемо повторное введение метода в классы.

Спасибо, я буду работать над своим кодом. :)

+0

Какова фактическая проблема, с которой вы сталкиваетесь? Все, что вы сделали, это предоставить образец кода, но нет объяснений, чтобы пойти с ним. –

+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; 

Как у вас в вашем коде, исключение в конструкторе приведет к окончательно блокировать ход и пытается звонить бесплатно на неинициализированной ссылке.