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
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.048 Beiträge
 
Delphi 12 Athens
 
#1

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 13:03
Zitat:
Das wäre aber auch nicht so gut, wenn Delphi das einfach so machen würde, denn es kann ja gewollt sein, daß IBaseInterface nicht supported wird und was macht man dann?
Genau darauf will ich ja hinaus: Gibt es diesen Fall? Ich hätte gesagt nein, da ich über das IExtendedInterface auch das IBaseInterface implementiere.
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.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Mikkey

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

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 13:35
Zitat:
Das wäre aber auch nicht so gut, wenn Delphi das einfach so machen würde, denn es kann ja gewollt sein, daß IBaseInterface nicht supported wird und was macht man dann?
Genau darauf will ich ja hinaus: Gibt es diesen Fall? Ich hätte gesagt nein, da ich über das IExtendedInterface auch das IBaseInterface implementiere.
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.
Tut mir leid, wenn ich da widerspreche, aber wenn ein Objekt das Interface IExtendedInterface anbietet muss es per Definition auch IBaseInterface anbieten.

Wenn ich eine Klasse definiere, die IExtendedInterface implementiert, bekomme ich schließlich auch einen Compilerfehler, wenn sie nicht die Methoden von IBaseInterface implementiert.

Wenn ich den obigen Code leicht modifiziere, wird er vom Compiler anstandslos geschluckt:

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.
  Mit Zitat antworten Zitat
alda

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

AW: Polymorphie und Interfaces in Delphi

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

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

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 14: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
Mikkey

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

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
Patito

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

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 14: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.114 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 15: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
 
#8

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 15: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
Mikkey

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

AW: Polymorphie und Interfaces in Delphi

  Alt 3. Jun 2014, 16:09
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....
Da spielt nur mein etwas älteres XE nicht mit, nur die Variante mit zwei voneinander abgeleiteten Klassen s.o. funktioniert.

Zitat:
Ein realitätsnahes Beispiel hierfür will mir aber auch nicht einfallen.
Mir auch nicht. Selbst wenn so etwas aus irgendeiner Notwendigkeit gemacht werden würde, hielte ich es für extrem schlechten Stil, wenn eine Methode gleichen Namens einer Objektinstanz verschiedene Dinge tut.

Geändert von Mikkey ( 3. Jun 2014 um 17:06 Uhr)
  Mit Zitat antworten Zitat
Patito

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

AW: Polymorphie und Interfaces in Delphi

  Alt 4. Jun 2014, 12:54
[...]
Ein realitätsnahes Beispiel hierfür will mir aber auch nicht einfallen.
Ein Beispiel wären z.B. Methoden zum Schreiben eines Logfiles im Basis-Interface:

Delphi-Quellcode:
IBase = interface(IInterface)
  procedure SetLogfile(const FileName: TFileName);
  procedure WriteLog(const LogInfo: String);
end;

IRead = interface(IBase);
IWrite = interface(IBase);
Die Interfaces zum Schreiben der Log-Infos sind in IRead und IWrite dieselben, aber Reader und Writer
könnten unterschiedliche Logfiles verwenden.

Dass man Interface-Methoden beliebig auf eigene Implementierungen mit anderem Namen umbiegen kann ist
ein recht zentrales Feature von Interfaces. Es löst die ganzen Probleme, die man in anderen Programmiersprachen
bei rein Klassen-basierter Mehrfachvererbung hat (C++).
Mehr oder weniger ist das mal ein Featur, bei dem man mal von einem echten Vorteil von Delphi sprechen könnte.
  Mit Zitat antworten Zitat
Antwort Antwort


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 07:49 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