2

私は次のようなコードを実行しようとしています:

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 インターフェイスを実行するにはどうすればよいですか?

なるほど。

追加:

皆さんありがとう。理解します。

同じ結果で 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);
    }
   ..........

Delphi のサンプル コード:

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

1 に答える 1

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戻ってくるはずです。または、参照カウントのライフタイム管理の使用を停止する必要があるかもしれません。ここから確認するのは非常に難しいです。IFooT

于 2012-09-09T19:45:53.003 に答える