2012-09-09 52 views
2

我想要的執行這樣的代碼:呼叫TObject.GetInterface免費對象

IFoo = Interface 
    procedure DoFoo; 
end; 

TFoo = class (TInterfaceObject, IFoo) 
    ..... 
    procedure DoFoo; 
end; 

TFoo2 = class (TInterfaceObject) 
    ...... 
end; 

TGenClass = class 
    class function DoSomething<T: class, cronstructor>: T; 
end; 

class function TGenClass.DoSomething<T>: T; 
var Obj: T; 
    Foo: IFoo; 
begin 
    Obj := T.Cretae; 
    if Obj.GetInterfaceEntry(IFoo) <> nil then 
    begin 
    Obj.GetInterface(IFoo, Foo); 
    Foo.DoFoo; 
    end; 
    result := Obj; 
end; 
...... 
var f: TFoo; 
    f2: TFoo2; 
begin 
    f:= TGenClass.DoSomeThing<TFoo>; 
    f2:= TGenClass.DoSomeThing<TFoo2>; 
    f2.free; 
    f.free; 
end; 

當我執行這個代碼,f.free提出一個例外,因爲已經是免費的,我想,因爲如果我評論此行

Obj.GetInterface(IFoo, Foo); 
Foo.DoFoo; 

它的工作。

¿如何在沒有自由對象的情況下執行IFoo接口?

thk。

地址:

謝謝大家。我明白。

我試着用同樣的結果返回IFoo。我的問題是T不能是TInterfacedObject。我想轉換的Java代碼:

public void dataIterate(int recNo, ResultSet data) throws SQLException { 

    try { 

     Constructor c = itemClass.getDeclaredConstructor(); 
     c.setAccessible(true); 
     Object item = c.newInstance(); 
     if (item instanceof CustomInitialize) ((CustomInitialize)item).initialize(data); 
     else { 

      if (metadata == null) metadata = data.getMetaData(); 
      for (int i=1; i<= metadata.getColumnCount(); i++) 
       assignProperty(itemClass, item, "set"+metadata.getColumnName(i).toLowerCase(), data.getObject(i)); 

     } 
     add((E)item); 

    } catch (Exception ex) { 
     throw new SQLDataException(ex); 
    } 
    .......... 

德爾福示例代碼:

program Project4; 

{$APPTYPE CONSOLE} 

{$R*.res} 

uses 
    System.SysUtils, System.Rtti; 

type 
    IFoo = Interface 
    ['{F2D87AE6-1956-4B82-A28F-DC011C529849}'] 
    procedure DoFoo; 
    end; 

    TFoo = class (TInterfacedObject, IFoo) 
    private 
    FName: String; 
    public 
    procedure DoFoo; 
    property Name: String Read FName write FName; 
    end; 

    TFoo2 = class (TObject) 
    private 
    FName: String; 
    published 
     property Name: String Read FName write FName; 
    end; 

TGenClass = class 
    class function DoSomething<T: class, constructor>: T; 
end; 

class function TGenClass.DoSomething<T>: T; 
var Obj: T; 
    Foo: IFoo; 
    Ap: TRttiProperty; 
    Ctx: TRttiContext; 
begin 
    Obj := T.Create; 
    if Obj.GetInterfaceEntry(IFoo) <> nil then 
    begin 
    Obj.GetInterface(IFoo, Foo); 
    Foo.DoFoo; 
    end; 
    Ctx.GetType(TypeInfo(T)).GetProperty('Name').SetValue(TObject(Obj),'AName'); 
    result := Obj; 
end; 
{ TFoo } 

procedure TFoo.DoFoo; 
begin 
    writeln('Foo executed.'); 
end; 
var f: TFoo; 
    f2:TFoo2; 
begin 
    try 
    f:= TGenClass.DoSomeThing<TFoo>; 
    f2:= TGenClass.DoSomeThing<TFoo2>; 
    writeln(f2.Name); 
    writeln(f.Name); //<-- raise exception 
    f.free; 
    f2.Free; 
    readln; 

    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
+6

請不要發佈虛假代碼。請發佈您的真實代碼。代碼編譯。使用剪貼板來實現這個目標。 –

+0

你究竟想要完成什麼?並請張貼編譯的代碼。 –

+0

我想將java代碼轉換爲delphi。其中,一個對象是從一個類引用創建的,如果實現了一個接口,就執行它。 – jlra

回答

4

讓我們來看看這個代碼:

class function TGenClass.DoSomething<T>: T; 
var Obj: T; 
    Foo: IFoo; 
begin 
    Obj := T.Create; 
    if Obj.GetInterfaceEntry(IFoo) <> nil then 
    begin 
    Obj.GetInterface(IFoo, Foo); 
    Foo.DoFoo; 
    end; 
    result := Obj; 
end; 

Obj := T.Create,對象具有參考計數爲零,因爲沒有接口變量尚未引用它。然後,您撥打GetInterface並參加Foo的界面參考。因此,該對象的引用計數爲1.然後該函數返回並且Foo超出範圍。這將參考計數減少到0,因此對象被釋放。

當您使用TInterfacedObject時,您必須始終保存一個接口變量。以便引用計數可以管理對象的生命。在這種情況下,你有混合的對象引用和接口變量,總是會導致痛苦和痛苦。

我真的不能告訴你你的代碼應該是什麼樣子,因爲我不知道你的問題是什麼。我所做的一切都是爲了解釋你的行爲。也許DoSomething應該返回IFoo而不是T。或者,您可能需要停止使用參考計數的生命週期管理。從這裏很難確定。