2

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

2 に答える 2

5

オブジェクトへのインターフェイスのキャストは、Delphi 2010以降で使用できます。古いバージョンのDelphiの回避策はどこにありますか。たとえば、Delphiでインターフェイスをオブジェクトにキャストする方法を参照してください。

于 2013-01-28T09:19:46.777 に答える
5

このLoad関数は、Delphiのすべてのバージョンで完全に機能します。問題はあなたのキャストです。これは安全でないタイプキャストとして知られているものです。インターフェイス参照からオブジェクトへの安全でない型キャストは、古いバージョンのDelphiでは明確に定義されていない動作をします。ただし、動作は最新のDelphiで明確に定義されています。ドキュメントには詳細が記載されています。

したがって、基本的な問題は、動作に対する期待がDelphi7バージョンの言語と互換性がないことです。

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.

インターフェイスから実装オブジェクトを要求するのはかなり珍しいことです。そうすることは、あなたのデザインに問題があることを示唆しています。本当にそうする必要がある場合は、いくつかのオプションがあります。

後者のオプションは、Delphiのすべてのバージョンで機能し、巧妙に機能することなく機能します。

于 2013-01-28T09:20:55.903 に答える