Einzelnen Beitrag anzeigen

Mikkey

Registriert seit: 5. Aug 2013
265 Beiträge
 
#15

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 14:38
Ein Problem mit solchen impliziten Cast hat man, wenn die Klasse implizit mehrere Versionen des Basis-Interfaces hat.
Z.B. TKlasse = class(TObject, IExtendedInterface_1, IExtendedInterface_2). Welche Implementierung soll man nehmen? (Die
Implementierungen können unterschiedlich delegiert sein...)

Der Compiler könnte sich natürlich etwas mehr Mühe machen in eindeutigen Fällen ein passendes Interface zu suchen,
aber die mit impliziten Cast verbundene Raterei verursacht eigentlich immer an unerwarteter Stelle Probleme.
Dein Beispiel zieht nicht, weil die Delphi-Syntax keine zwei Implementierungen einer Funktion der Vorfahrenklasse erlaubt. Im folgenden Code habe ich das mal über zwei voneinander erbenden Klassen versucht, aber damit bekommt man auch nicht den Aufruf verschiedener Implementierungen hin:

Delphi-Quellcode:
unit IFTest;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  IBase = interface(IInterface)
    function f1(): Integer;
  end;

  IExtend1 = interface(IBase)
    function f2(): Integer;
  end;

  IExtend2 = interface(IBase)
    function f3(): Integer;
  end;

  TK1 = class(TInterfacedObject, IExtend1)
    function f1(): Integer; virtual;
    function f2(): Integer;
  end;

  TK2 = class(TK1, IExtend2)
    function f1(): Integer; override;
    function f3(): Integer;
  end;

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure testF(i: IBase);
begin
end;

function TK1.f1(): Integer;
begin
  result := 11;
end;

function TK1.f2(): Integer;
begin
  result := 12;
end;

function TK2.f1(): Integer;
begin
  result := 21;
end;

function TK2.f3(): Integer;
begin
  result := 23;
end;


procedure TForm1.FormCreate(Sender: TObject);
var
  o1: TK1;
  o2: TK2;
  i1, i2, i3: Integer;
begin
  o1 := TK1.Create();
  o2 := TK2.Create();
  testF(IExtend1(o1));
  testF(IExtend2(o2));
  i1 := o1.f1();
  i2 := o2.f1();
  i3 := (TK1(o2)).f1();
  ShowMessage(Format('o1: %d, o2: %d, Base(o2): %d', [i1, i2, i3]));
  // Ausgabe: 11 / 21 / 21
end;

end.
Möglicherweise könnte das aber irgendwann mal klappen, insoweit könnte Uwe Raabes Einwand gerechtfertigt sein.

Edit:
Ziehe meinen Einwand zurück, mit "reintroduce" in der TK2-Definition (anstelle "virtual"/"override") wird tatsächlich 11/21/11 ausgegeben.

Geändert von Mikkey ( 3. Jun 2014 um 15:18 Uhr)
  Mit Zitat antworten Zitat