我正在尝试执行下面这样的代码:
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;发布于 2012-09-10 03:45:53
让我们来看看这段代码:
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之后,对象的引用计数为零,因为还没有接口变量引用它。然后在Foo中调用GetInterface并获取一个接口引用。因此,对象现在的引用计数为1,然后函数返回,Foo超出作用域。这会将引用计数减少到0,因此对象会被释放。
使用TInterfacedObject时,必须始终保留接口变量。这样引用计数就可以管理对象的生命周期。在这种情况下,您有混合的对象引用和接口变量,这必然会导致痛苦和痛苦。
我真的不能建议你的代码应该是什么样子的,因为我不知道你的问题是什么。我所做的一切都是为了向你解释这种行为。也许DoSomething应该返回IFoo而不是T。或者,您可能需要停止使用引用计数的生命周期管理。从这里很难确定。
https://stackoverflow.com/questions/12342313
复制相似问题