AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi Fehlende Mehrfachvererbung bei Schnittstellen
Thema durchsuchen
Ansicht
Themen-Optionen

Fehlende Mehrfachvererbung bei Schnittstellen

Ein Thema von Der schöne Günther · begonnen am 17. Jul 2014 · letzter Beitrag vom 18. Jul 2014
Antwort Antwort
Der schöne Günther

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

AW: Fehlende Mehrfachvererbung bei Schnittstellen

  Alt 17. Jul 2014, 19:05
Als Ergänzung vielleicht noch: So würde ich es in Java machen:

Code:
class App
{
   public static void main (String[] args) throws java.lang.Exception
   {
      IBoth myVar = new BothImplementer();
      myVar.subMethod1();
      myVar.subMethod2();
   }
}

interface IBase {
   // Stub
}

interface ISub1 extends IBase {
   void subMethod1();
}

interface ISub2 extends IBase {
   void subMethod2();
}

// Reines Tagging-Interface
interface IBoth extends ISub1, ISub2 {}

// Muss das Tagging-Interface implementieren
class BothImplementer implements ISub1, ISub2, IBoth {
   public void subMethod1() {
      System.out.println("submethod1");
   }
   public void subMethod2() {
      System.out.println("submethod2");
   }
}
In Delphi ist die Deklaration von IBoth nicht möglich.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Fehlende Mehrfachvererbung bei Schnittstellen

  Alt 17. Jul 2014, 19:22
Schlimm ist ja, daß selbst ein Singlepasscompiler, wie Delphi, theoretisch Mehrfachvererbung anbieten könnte,
also rein von den "sichtbaren" Schnittstellen, welche der Programmierer sieht. (vor dem Compilieren)

Man würde einfach nur beim neuen "kombinierten" Objekt/Interface die direkten Schnittstellen der Vorfahren nochmals durch den Compiler jagen und dabei die bekannten Fehlermeldungen werfen, wenn sich etwas überschneidet.
Zitat:
[dcc32 Fehler] Unit23.pas(39): E2254 Die überladene Prozedur 'Read' muss mit der Direktive 'overload' gekennzeichnet sein

[dcc32 Fehler] Unit23.pas(39): E2252 Es gibt bereits eine Methode 'Read' mit identischen Parametern
Nur bei der RTTI müsste man sich was überlegen, wie man das macht.
Und auch die IS/AS-Prüfungen, und Ähnliches, würden etwas aufwändiger, da man dann ja keine lineare Vererbung mehr hat, sondern einen Baum.


Aber nein, es ist dennoch nicht möglich, in Delphi eine Mehrfachvererbung hinzubekommen.
(jedenfalls nicht so, daß man die Typen, so wie es jetzt möglich ist, einfach so blind in die neuen Vererbungslinien casten kann)
In dynamischen Sprachen, welche paktisch alles zur Laufzeit parsen und nicht mit festen Indize/Adressen arbeiten, wie z.B. Java/PHP/JavaScript, ist das halt was Anderes.

Klasse/Interface 1
* Addresse 1 = Funktion A
* Addresse 2 = Funktion B

Klasse/Interface 2
* Addresse 1 = Funktion C
* Addresse 2 = Funktion D

Klasse/Interface 1+2
* Addresse 1 = Funktion A oder Funktion C
* Addresse 2 = Funktion B oder Funktion D

(das Selbe nochmal für alle Felder/Variablen in der Klasse usw.)


Wenn man jetzt auf Adresse 1 zugreift, bei wem soll man denn nun rauskommen?
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (17. Jul 2014 um 19:35 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Fehlende Mehrfachvererbung bei Schnittstellen

  Alt 17. Jul 2014, 19:38
Auch für Delphi ist das "möglich", aber man muß da etwas aufpassen und in den zweiten, dritten und x-ten Vererbungslinien, neben der Hauptvererbungslinie, sind bestimmte Dinge nicht mehr möglich.

In dem neuen kombinierten Typen ist dann (intern) nur die erste Vererbungslinie wirklich vererbt und alle anderen Felder/Funktion sind praktisch in den neuen Typen reinkopiert. (so wie bei den Generics)
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

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

AW: Fehlende Mehrfachvererbung bei Schnittstellen

  Alt 17. Jul 2014, 21:31
Jetzt mal etwas out-of-the-box gedacht (weiß nicht, ob das hier taugt):

Delphi-Quellcode:
type
  IBase = interface
  end;

  ISub1 = interface (IBase)
  end;

  ISub2 = interface (IBase)
  end;

  IBoth = interface
    function GetSub1: ISub1;
    function GetSub2: ISub2;
    property Sub1: ISub1 read GetSub1;
    property Sub2: ISub2 read GetSub2;
  end;

type
  TFluxKompensator = class(TInterfacedObject, ISub1, ISub2, IBoth)
    function GetSub1: ISub1;
    function GetSub2: ISub2;
  end;

function TFluxKompensator.GetSub1: ISub1;
begin
  result := Self;
end;

function TFluxKompensator.GetSub2: ISub2;
begin
  result := Self;
end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.045 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#5

AW: Fehlende Mehrfachvererbung bei Schnittstellen

  Alt 17. Jul 2014, 22:35
Ich hab grad son Deja Vu, das Thema hatten wir doch neulich erst

Generell stell ich mir immer die Frage, warum man vom einen Interface auf ein anderes kommen sollte. Das ISP gibt's ja nicht umsonst.

Wenn also ein Programmteil IDiesesDings konsumiert, warum sollte es dann darauf schauen, ob das Objekt dahinter nich auch zufällig noch IJenesDings implementiert und damit was machen. Klar, mag es Fälle geben, aber generell ist das eher ein Architektursmell, wenn man sowas braucht. Das geht ein wenig in die Richtung Leaky Abstraction.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Patito

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

AW: Fehlende Mehrfachvererbung bei Schnittstellen

  Alt 18. Jul 2014, 07:42
Ich hab grad son Deja Vu, das Thema hatten wir doch neulich erst

Generell stell ich mir immer die Frage, warum man vom einen Interface auf ein anderes kommen sollte. Das ISP gibt's ja nicht umsonst.
Bei Mehrfachvererbung will man auf einen bekannten Parent casten können. (Man will z.B. ein Interface
als Parameter an eine Prozeduren übergeben können, die als Parameter ein ParentInterface erwartet).

Das ISP will, dass man nicht unnötig große Schnittstellen übergiebt, und genau das ist es, was der Cast auf den Parent macht.
Leider geht das in Delphi eben nicht ganz ohne Bastelei, daher ist sowas leider immer wieder ein Thema...
  Mit Zitat antworten Zitat
Der schöne Günther

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

AW: Fehlende Mehrfachvererbung bei Schnittstellen

  Alt 18. Jul 2014, 08:04
Vielen Dank für die ganzen schlauen Beiträge.

Ich glaube die Beiträge von Uwe und BUG sind in Sachen Lösung wohl das, worauf es in Delphi am besten hinausläuft.
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.045 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#8

AW: Fehlende Mehrfachvererbung bei Schnittstellen

  Alt 18. Jul 2014, 10:01
Bei Mehrfachvererbung will man auf einen bekannten Parent casten können. (Man will z.B. ein Interface
als Parameter an eine Prozeduren übergeben können, die als Parameter ein ParentInterface erwartet).
Bei diesem Usecase stimme ich dir zu.

Leider geht das in Delphi eben nicht ganz ohne Bastelei, daher ist sowas leider immer wieder ein Thema...
Als große Bastelei würd ich es nicht bezeichnen, allerdings kann man es nicht designtechnisch 100%ig sauber lösen,
da es ein Implementierungsdetail wird und nicht über die Interfacedefinition ersichtlich ist.
Zudem hat man leider keine Compile time safety.

Delphi-Quellcode:
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  IBar = interface
    ['{F2BDC6D3-6E79-48EF-99A9-94DE53C035DC}']
    procedure DoIt;
  end;

  IBaz = interface
    ['{3E99A294-48EF-4E2A-B077-562462997EA7}']
    procedure DoIt;
  end;

  IFoo = interface{(IBar, IBaz)}
    ['{F2173B9B-43A5-4631-A08B-7D64102F1867}']
  end;

  TFoo = class(TInterfacedObject, IBar, IBaz, IFoo) // in C#: Foo : IFoo
  protected
    procedure DoIt;
  end;

procedure TFoo.DoIt;
begin
  Writeln('DoIt')
end;

procedure DoSomething(const bar: IBar);
begin
  bar.DoIt;
end;

var
  foo: IFoo;
begin
  foo := TFoo.Create;
  DoSomething(foo as IBar);
  Readln;
end.
P.S: Ich hab mich gerade mal mit meinem Kollegen zusammen gesetzt, der C# beherrscht und uns angeschaut, was diese "Multiple Interface Inheritance" in C# so macht.
Wir sind zu dem Schluss gekommen, dass es letztlich nur Syntax Sugar ist, was dafür sorgt, dass eine Klasse die ein Interface implementiert, welches von verschiedenen anderen "abgeleitet" ist, diese auch implementiert. Auch beim Übergeben eines solchen Interfaces an eine Methode, welche eins der Elterninterfaces erwartet, benötigt man dann keinen Cast, sondern kann es so übergeben. Letztlich ist es aber dasselbe wie ich oben im Delphi Code geschrieben habe, nur ein wenig typensicherer.

Im Übrigen lässt C# ein foo.DoIt() nicht zu und quittiert es mit einem "ambiguous call" Compilerfehler.
Und auch die Reflection zeigt einem, dass die Klasse alle 3 Interfaces implementiert, obwohl man eigentlich nur IFoo hingeschrieben hat.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (18. Jul 2014 um 10:41 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#9
  Alt 17. Jul 2014, 19:23
Du könntest die Hierarchie auch auf den Kopf stellen:
Dein Messgerät hat allgemeine Schnittstelle (IMessgerät), welche zusätzliche Sichten auf Messgerät (also die anderen Interfaces) erzeugen kann. Vererbung gibt es unter den Interfaces keine. Die Klassen, welche IMessgerätLivedatenfähig (und so weiter) bereitstellen, müssen dabei noch nicht einmal mit TFluxKompensator verwandt sein, sondern werden vielleicht nur von der TFluxKompensator-Instanz zur Laufzeit erstellt und konfiguriert.

Aber nein, es ist dennoch nicht möglich, in Delphi eine Mehrfachvererbung hinzubekommen.
In dynamischen Sprachen, welche paktisch alles zur Laufzeit parsen und nicht mit festen Indize/Adressen arbeiten, wie z.B. Java/PHP/JavaScript, ist das halt was Anderes.
Du weißt schon, das C++ Mehrfachvererbung anbietet, sicher keine dynamische Sprache ist und man dort trotzdem den meisten Probleme bei der Mehrfachvererbung relativ intuitiv umgehen kann

Eigentlich sollte es mit "Mehrfachvererbung" von Interfaces überhaupt kein Problem geben, eben weil nur eine Schnittstellenbeschreibung ohne Implementierung ist.

Geändert von TBx (18. Jul 2014 um 08:28 Uhr) Grund: Doppelpost aufgelöst
  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 00:10 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz