delphi - Delphi 7 和 Delphi XE 及更高版本之间接口(interface)的不同行为

标签 delphi interface delphi-7 delphi-xe

我在不同版本的 Delphi 中使用界面时遇到一个奇怪的问题。以下最小化代码在 Delphi XE 和更高版本中按预期编译和运行,但在 Delphi 7 中没有。具体来说,在 Delphi 7 中编译时,function TForm1.Load: IMoleculeSubject; 似乎没有返回正确的结果,即对新创建实例的正确引用。你能帮忙评论一下原因和可能的解决方法吗?非常感谢!

uInterface.pas

    unit uInterface;
    
    interface
    
    type
    
      IMoleculeSubject = interface
      ['{BEB4425A-186C-45DF-9DCE-C7175DB0CA90}']
      end;
    
      TMoleculeSubject = class(TInterfacedObject, IMoleculeSubject)
      end;
    
    implementation
    
    end.
    

uBusiness.pas

    unit uBusiness;
    
    interface
    
    uses
      uInterface;
    
    type
    
      TMoleculeDecorator = class(TMoleculeSubject) 
      private
        FID: Integer;
      public           
        property ID: Integer read FID;
        constructor Create;
      end;
    
    implementation
    
    { TMoleculeDecorator }
    
    constructor TMoleculeDecorator.Create;
    begin
      inherited Create;
    
      FID := Random(100);
    end;
    
    end.

Unit1.pas

    unit Unit1;
    
    interface
    
    uses
      uInterface, uBusiness,
    
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, 
      Forms, Dialogs;
    
    type
      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
      private
        function Load: IMoleculeSubject;
      public
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      MolSubject: IMoleculeSubject;
    begin
      MolSubject := Load;
    
              // The down-cast is to show the returned result is wrong in Delphi 7!
      Caption := IntToStr(TMoleculeDecorator(MolSubject).ID);
    end;
    
    function TForm1.Load: IMoleculeSubject;   
    var
      MolSubject: IMoleculeSubject;
    begin
      MolSubject := TMoleculeDecorator.Create;
      Result := MolSubject;
    end;
    
    end.
    
    

最佳答案

Load 函数在所有版本的 Delphi 中都运行良好。问题在于您的转换,即所谓的不安全类型转换。从接口(interface)引用到对象的不安全类型转换在旧版本的 Delphi 中具有错误定义的行为。然而,行为在现代 Delphi 中是明确定义的。 documentation说得更多。

因此,基本问题是您对该行为的期望与该语言的 Delphi 7 版本不兼容。

如果你得到返回ID的接口(interface)你会发现你创建的接口(interface)是符合预期的。

program InterfaceDemo;

{$APPTYPE CONSOLE}

uses
  Classes;

type
  IMyIntf = interface
    function GetID: Integer;
  end;

  TImplementingObject = class(TInterfacedObject, IMyIntf)
  private
    FID: Integer;
    function GetID: Integer;
  public
    constructor Create;
  end;

{ TImplementingObject }

constructor TImplementingObject.Create;
begin
  FID := Random(100);
  Writeln(FID);
end;

function TImplementingObject.GetID: Integer;
begin
  Result := FID;
end;

var
  MyIntf: IMyIntf;

begin
  Randomize;
  MyIntf := TImplementingObject.Create;
  Writeln(MyIntf.GetID);
  Readln;
end.

从接口(interface)请求实现对象是相当不寻常的。这样做表明您的设计存在问题。如果您确实需要这样做,有以下几种选择:

后一种选择适用于所有版本的 Delphi,并且无需诉诸诡计。

关于delphi - Delphi 7 和 Delphi XE 及更高版本之间接口(interface)的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14558704/

相关文章:

delphi - 如何构建 const 数组?

Java 实例与抽象类和方法

arrays - 增加指针数组的通用函数

java - 是否可以在接口(interface)内创建 JUnit 规则

java - 在JAVA中实例化接口(interface)?

delphi - FastMM4 说 "The block header has been corrupted"

delphi - 你能帮忙把这个非常小的 C++ 组件翻译成 Delphi 吗?

delphi - 在 Delphi 中的远程系统上执行 Postgres 查询时获取本地系统路径

delphi - 什么应该是一个简单的 TCP 客户端服务器,,STUCK

multithreading - Thread.FreeOnTerminate := True, 内存泄漏和幽灵运行