AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Polymorphie und Interfaces in Delphi

Ein Thema von Neutral General · begonnen am 3. Jun 2014 · letzter Beitrag vom 4. Jun 2014
Antwort Antwort
Seite 2 von 3     12 3      
alda

Registriert seit: 24. Mär 2014
Ort: Karlsruhe
93 Beiträge
 
Delphi XE6 Architect
 
#11

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 14:55
Zitat:
Diesen Fall wird es spätestens in dem Moment geben, wo Delphi das nicht mehr unterstützen würde. Die Tatsache, daß wir uns vielleicht im Moment keinen derartigen Fall vorstellen können, ist allenfall ein Zeichen unseres beschränkten Denkens und kein Beweis, daß es ihn nicht gibt oder geben wird.
Da kann ich natürlich nicht widersprechen, schön gesagt

Dennoch bin ich da auch auf Mikkey's Seite.
Zitat:
Es fehlt also schlicht und einfach der implizite Cast von Objektreferenz auf das implementierte Interface.
-> Das sehe ich genau so.

Man verwendet die Ableitung (also die Abhängigkeit) von Interfaces ja aus einem trifftigen Grund .. und der ist für mich: jemand der das Subinterface implementiert, muss auch das Superinterface bereitstellen (implementieren).

Beispiel:
Delphi-Quellcode:
IObjectReader = interface
 GetName: String;

 property Name: String read GetName;
end;

IObjectWriter = interface(IObjectReader)
 SetName(const AValue: String);

 property Name: String read GetName write SetName;
end;
Also eine Klasse die den Schreibzugriff über IObjectWriter anbietet, muss auch den Lesezugriff über IObjectReader anbieten (sonst würde der Compiler meckern aufgrund der Property).

Geändert von alda ( 3. Jun 2014 um 14:57 Uhr)
  Mit Zitat antworten Zitat
Patito

Registriert seit: 8. Sep 2006
108 Beiträge
 
#12

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 15:02
Delphi-Quellcode:
var obj: TKlasse;
begin
  // ...
  Irgendwas(IExtendedInterface(obj));
end;
Es fehlt also schlicht und einfach der implizite Cast von Objektreferenz auf das implementierte Interface.
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.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#13

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 15:09
Genau darauf will ich ja hinaus: Gibt es diesen Fall? Ich hätte gesagt nein, da ich über das IExtendedInterface auch das IBaseInterface implementiere.
Vererben ist bei Interfaces halt ein bissl anders.
Von außen kann man nicht auf die Methoden des Vorfahren zugreifen.
Man kommt da nur daran, wenn man die Interfaceinstanz auf den Vorfahren castet (als Typcast und nicht über Supports), wenn man weiß, daß dort etwas drin ist.

Ich hatte das mal verwendet, um in der Codevervollständigung die Liste kürzer zu halten, da man in Interfaces keine private-Abschnitt deklarieren kann, worin sich Getter und Setter verstecken lassen.
Miniaturansicht angehängter Grafiken
unbenannt.png  
$2B or not $2B

Geändert von himitsu ( 3. Jun 2014 um 15:20 Uhr)
  Mit Zitat antworten Zitat
alda

Registriert seit: 24. Mär 2014
Ort: Karlsruhe
93 Beiträge
 
Delphi XE6 Architect
 
#14

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 15:19
Zitat:
Man kommt da nur daran, wenn man die Interfaceinstanz auf den Vorfahren castet (als Typcast und nicht über Supports), wenn man weiß, daß dort etwas drin ist.
Das ist ein Spezialfall. Der Vorfahre alleine repräsentiert nur zwei alleinstehende, öffentliche Methoden (Setter und Getter, ohne zugehörige Property). Sobald Du über den Nachfahren gehst, erkennt Delphi, dass die Getter und Setter zu der Property gehören. In meinem Beispiel hättest Du auf dem Nachfahren auch den Zugriff auf die Methoden des Vorfahren (also wie auch bei normalen Methoden, ohne Properties)

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

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

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 15: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 16:18 Uhr)
  Mit Zitat antworten Zitat
Patito

Registriert seit: 8. Sep 2006
108 Beiträge
 
#16

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 15:47
Dein Beispiel zieht nicht, weil die Delphi-Syntax keine zwei Implementierungen einer Funktion der Vorfahrenklasse erlaubt.
Schau Dir die Syntax zum implementieren und deligieren von Interfaces noch mal genau an....
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.176 Beiträge
 
Delphi 10 Seattle Enterprise
 
#17

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 16:04
Dein Beispiel zieht nicht, weil die Delphi-Syntax keine zwei Implementierungen einer Funktion der Vorfahrenklasse erlaubt.
Schau Dir die Syntax zum implementieren und deligieren von Interfaces noch mal genau an....

Wollte ich auch grade sagen. Stichwort "Method Resolution clause". Hier ein Beispiel:

Delphi-Quellcode:
program Project4;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
   IBaseInterface = interface
      procedure baseMethod();
   end;

   IChildInterface1 = interface(IBaseInterface)
      // Stub
   end;

   IChildInterface2 = interface(IBaseInterface)
      // Stub
   end;

   TMyObject1 = class(TInterfacedObject, IChildInterface1)
      public procedure baseMethod(); virtual; abstract;
   end;

   TMyObject2 = class(TMyObject1, IChildInterface1, IChildInterface2)
      procedure baseForChildInterface1();
      procedure baseForChildInterface2();

      procedure IChildInterface2.baseMethod = baseForChildInterface1;
      procedure IChildInterface1.baseMethod = baseForChildInterface2;
   end;

{ TMyObject2 }

procedure TMyObject2.baseForChildInterface1();
begin
   WriteLn('Das ist "baseForChildInterface1()"');
end;

procedure TMyObject2.baseForChildInterface2();
begin
   WriteLn('Das ist "baseForChildInterface2()"');
end;

var
   iChild1Reference: IChildInterface1;
   iChild2Reference: IChildInterface2;
   objRef: TMyObject2;

begin
   try

      objRef := TMyObject2.Create();

      iChild1Reference := objRef;
      iChild2Reference := objRef;

      iChild1Reference.baseMethod();
      iChild2Reference.baseMethod();

   except
      on E: Exception do
         WriteLn(E.ClassName, ': ', E.Message);
   end;

   readln;

end.
Ein realitätsnahes Beispiel hierfür will mir aber auch nicht einfallen.
  Mit Zitat antworten Zitat
alda

Registriert seit: 24. Mär 2014
Ort: Karlsruhe
93 Beiträge
 
Delphi XE6 Architect
 
#18

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 16:08
Zitat:
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...)
Danke, der Gedankengang hatte mir gefehlt.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#19

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 16:13
Hmmm, das ist jetzt komisch.

Delphi-Quellcode:
type
  IMyIntf = interface
    function Getter: Integer;
    procedure Setter(i: Integer);
    property Prop: Integer read Getter write Setter;
  end;
Ich weiß jetzt nicht mehr welche Delphi-Version das war, aber damals wurde der Getter und Setter nicht ausgeblendet, was XE jetzt aber macht.

Delphi-Quellcode:
type
  IInnerMyIntf = interface
    function Getter: Integer;
    procedure Setter(i: Integer);
  end;
  IMyIntf = interface(IInnerMyIntf)
    function Abc: Integer;
  end;
Dafür wird im IMyIntf der Getter/Setter jetzt doch angezeigt.

Hmmmmmmmmm.
$2B or not $2B
  Mit Zitat antworten Zitat
alda

Registriert seit: 24. Mär 2014
Ort: Karlsruhe
93 Beiträge
 
Delphi XE6 Architect
 
#20

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 16:16
Zitat:
Ich weiß jetzt nicht mehr welche Delphi-Version das war, aber damals wurde der Getter und Setter nicht ausgeblendet, was XE jetzt aber macht.
Oh, das kann ich Dir auch nicht sagen. In meiner 2007er ist es schon so
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:32 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz