Delphi 7与Delphi XE及更高版本之间的接口行为不同

SOU*_*ser 2 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.
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

klu*_*udg 5

自Delphi 2010以来,可以使用对象的转换接口.旧的Delphi版本的解决方法在哪里,请参阅例如如何在Delphi中将接口转换为对象


Dav*_*nan 5

Load功能在所有版本的Delphi中都能很好地运行.问题是你的演员,这就是所谓的不安全的类型转换.来自对象的接口引用的不安全类型转换在旧版本的Delphi中具有不明确的行为.但是,这种行为在现代Delphi中得到了很好的定义.该文件说,越来越多.

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

如果您获得了返回ID的界面,您会发现您正在创建的界面符合预期.

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.
Run Code Online (Sandbox Code Playgroud)

从界面中请求实现对象是相当不寻常的.这样做表明您的设计存在问题.如果你真的需要这样做,有几个选择:

后一种选择适用于所有版本的Delphi,并且不需要借助于诡计.

  • 那么你使用接口的动机是什么?您似乎想要创建没有方法的接口.在哪种情况下,他们服务的目的是什么?如果不了解你的动机,很难提供建议.通常会创建包含方法声明的接口! (3认同)