gpt4 book ai didi

delphi - 多个接口(interface),Supports() 函数和引用计数

转载 作者:行者123 更新时间:2023-12-03 19:31:38 26 4
gpt4 key购买 nike

如果我理解正确,这很好:

type
IMyInterface = interface['{60E314E4-9FA9-4E29-A09A-01B91F2F27C7}']
procedure MyMethod;
end;

type
TMyIClass = class(TInterfacedObject, IMyInterface)
public
procedure MyMethod; // Forget the implementations in this example
end;

var
lMyIClass: IMyInterface;
lSupports: Boolean;
begin
lMyIClass := TMyIClass.Create;
lSupports := Supports(lMyIClass,IMyInterface);
Memo1.Lines.Add('lMyIClass supports IMyInterface: ' + BoolToStr(lSupports,true));
if lSupports then DoSomethingWith(lMyIClass);

现在我有一个实现多个接口(interface)的类:
type
IFirstInterface = interface['{4646BD44-FDBC-4E26-A497-D9E48F7EFCF9}']
procedure SomeMethod1;
end;

ISecondInterface = interface['{B4473616-CF1F-4E88-9EAE-1AAF1B01A331}']
procedure SomeMethod2;
end;

TMyClass = class(TInterfacedObject, IFirstInterface, ISecondInterface)
procedure SomeMethod1;
procedure SomeMethod2;
end;

我可以调用另一个重载的 Support() 返回接口(interface)并用它做一些事情):
var
MyClass1,MyClass2 : TMyClass;
i1: IFirstInterface;
i2: ISecondInterface;
bSupports: Boolean;
begin
Memo1.Clear;
MyClass1 := TMyClass.Create;

bSupports := Supports(MyClass1,IFirstInterface,i1);
if bSupports then
begin
Memo1.Lines.Add('MyClass1 supports IFirstInterface');
DoSomethingWith(i1);
end
else
Memo1.Lines.Add('MyClass1 does not support IFirstInterface');

bSupports := Supports(MyClass1,ISecondInterface,i2);
if bSupports then
begin
Memo1.Lines.Add('MyClass1 supports ISecondInterface');
DoSomethingElseWith(i2);
end
else
Memo1.Lines.Add('MyClass1 does not support ISecondInterface');

MyClass1 := nil;
i1 := nil;
i2 := nil;
MyClass2 := TMyClass.Create;

bSupports := Supports(MyClass2,IFirstInterface,i1);

if bSupports then
begin
Memo1.Lines.Add('MyClass2 supports IFirstInterface');
DoSomethingWith(i1);
end
else
Memo1.Lines.Add('MyClass2 does not support IFirstInterface');

bSupports := Supports(MyClass2,ISecondInterface,i2);
if bSupports then
begin
Memo1.Lines.Add('MyClass2 supports ISecondInterface');
DoSomethingElseWith(i2);
end
else
Memo1.Lines.Add('MyClass2 does not support ISecondInterface');

我对此有三个问题:
  • MyClass1, MyClass2现在是对象类型,而不是简单示例中的接口(interface)类型。这个可以吗?
  • 我应该 Free() 还是“nil” MyClass1 或者甚至不理会它?
  • 处理完 2. 后,是两个 ix:= nil关于引用计数仍然需要声明?
  • 最佳答案

    一个常见的建议是永远不要将对象引用与接口(interface)引用混合。这意味着如果您需要实例化一个类并使用它的任何接口(interface),最好不要通过对象引用类型来引用它。您将变量更改为 TMyClass 类型违反了该建议。而不是接口(interface)类型。将它们声明为接口(interface)变量;我会使用 IUnknown .

    这个建议的原因是对象引用与接口(interface)引用不同。编译器总是为接口(interface)变量插入引用计数代码,并且该代码忽略了程序中其他任何地方的任何对象引用。由于引用计数,对象引用变量在更改某些接口(interface)变量后可能会变得无效,并且在编写程序时很容易忽略这一点。如果您从来没有对象引用变量,那么您不必担心这种可能性;接口(interface)引用应始终有效。

    如果 MyClass1是一个对象引用,那么你不应该调用 Free将其分配给接口(interface)变量后。这是您的一些代码,带有对象的引用计数注释:

    MyClass1 := TMyClass.Create;  // initialized to 0

    bSupports := Supports(MyClass1,IFirstInterface,i1); // incremented to 1
    if bSupports then
    begin
    Memo1.Lines.Add('MyClass1 supports IFirstInterface');
    DoSomethingWith(i1);
    end
    else
    Memo1.Lines.Add('MyClass1 does not support IFirstInterface');

    bSupports := Supports(MyClass1,ISecondInterface,i2); // incremented to 2
    if bSupports then
    begin
    Memo1.Lines.Add('MyClass1 supports ISecondInterface');
    DoSomethingElseWith(i2);
    end
    else
    Memo1.Lines.Add('MyClass1 does not support ISecondInterface');

    MyClass1 := nil; // still 2
    i1 := nil; // decremented to 1
    i2 := nil; // decremented to 0; the object gets destroyed

    如果您要调用 MyClass1.Free在任何时候,您的程序都会崩溃。自己释放对象不会改变 i1 中的值或 i2 ,所以编译器自动插入的引用计数代码仍然会执行。它会尝试减少已释放对象的引用计数,这显然不好。

    但是假设你等到你清除了 i1i2 ,如在此代码中:
    i1 := nil;
    i2 := nil;
    MyClass1.Free;

    那还是错的。清除变量会将引用计数设置为 0,因此对象在分配给 i2 时会被销毁; MyClass1 中的值无效,因此您不应调用 Free在那里,要么。

    将对象引用分配给接口(interface)引用后,最安全的做法是立即清除对象引用。然后你就不会再想使用它了。

    通常不需要清除接口(interface)变量。它在其生命周期结束时被自动清除(对于局部变量,当它们在函数结束时超出范围时)。此外,如果您调用 Supports并传入一个已经分配的接口(interface)引用,它要么接收到新对象的接口(interface)引用,要么被清除;它不会继续保持之前的值。

    也就是说,当您调用 Supports(MyClass2,IFirstInterface,i1); ,无需清除 i1第一的。调用 Supports要么填写 i1引用 IFirstInterface MyClass2 引用的对象,否则它将存储 nili1 .

    关于delphi - 多个接口(interface),Supports() 函数和引用计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18148221/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com