![]() |
AW: Fehlende Mehrfachvererbung bei Schnittstellen
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; |
AW: Fehlende Mehrfachvererbung bei Schnittstellen
Ich hab grad son Deja Vu, das Thema hatten wir doch neulich erst :gruebel:
Generell stell ich mir immer die Frage, warum man vom einen Interface auf ein anderes kommen sollte. Das ![]() Wenn also ein Programmteil
Delphi-Quellcode:
konsumiert, warum sollte es dann darauf schauen, ob das Objekt dahinter nich auch zufällig noch
IDiesesDings
Delphi-Quellcode:
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.
IJenesDings
|
AW: Fehlende Mehrfachvererbung bei Schnittstellen
Zitat:
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... |
AW: Fehlende Mehrfachvererbung bei Schnittstellen
Vielen Dank für die ganzen schlauen Beiträge. :cheers:
Ich glaube die Beiträge von Uwe und BUG sind in Sachen Lösung wohl das, worauf es in Delphi am besten hinausläuft. |
AW: Fehlende Mehrfachvererbung bei Schnittstellen
Zitat:
![]() |
AW: Fehlende Mehrfachvererbung bei Schnittstellen
Ich wollte, mit einem mehr oder weniger konkreten Beispiel, schauen, wie andere es schreiben würden.
Das andere Thema geht ja eher (technisch) darum zu schauen, was und was nicht in Delphi geht; mit dem Fokus auf das "Herausfinden, das etwas implementiert wird". Mir ging es jetzt nicht um das Herausfinden, sondern um das "Wie am besten ansprechen?". Und wieso Januar? |
AW: Fehlende Mehrfachvererbung bei Schnittstellen
Zitat:
Zitat:
da es ein Implementierungsdetail wird und nicht über die Interfacedefinition ersichtlich ist. Zudem hat man leider keine Compile time safety.
Delphi-Quellcode:
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.
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. 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. |
AW: Fehlende Mehrfachvererbung bei Schnittstellen
Danke, du hast den Problemkreis sehr anschaulich beschrieben.
Der Delphicompiler müsste nur zwei Dinge zusätzliche beherschen:
Delphi-Quellcode:
Das vermisse ich eigentlich schon fast so lange, wie ich mit Interfaces in Delphi arbeite.
TFoo = class(TInterfacedObject, IFoo) // IBar, IBaz, alle Eltern durch den Compiler versteckt mit angelegt}
DoSomething(foo); // (foo as IBar) duch den Compiler automatische Abfrage des passenden Elter |
AW: Fehlende Mehrfachvererbung bei Schnittstellen
Zitat:
Delphi-Quellcode:
Das Hauptproblem ist aber hierbei, dass nach dem Aufruf von
procedure DoSomethingWithBar( ABar : IBar );
procedure DoSomethingWithBaz( ABaz : IBaz ); TFoo = class( TInterfacedObject, IBar, IBaz, IFoo ) ... end; var Foo : TFoo; begin Foo := TFoo.Create; DoSomethingWithBar( Foo ); DoSomethingWithBaz( Foo ); end;
Delphi-Quellcode:
die Foo-Instanz sich in Rauch auflöst. Somit müsste man entweder
DoSomethingWithBar( Foo );
Delphi-Quellcode:
von
TFoo
Delphi-Quellcode:
ableiten und explizit freigeben
TPersistentInterface
Delphi-Quellcode:
oder sich eben zusätzlich eine
TFoo = class( TInterfacedPersistent, IBar, IBaz, IFoo )
end; var Foo : TFoo; begin Foo := TFoo.Create; try DoSomethingWithBar( Foo ); DoSomethingWithBaz( Foo ); finally Foo.Free; end; end;
Delphi-Quellcode:
Referenz merken.
IFoo
Delphi-Quellcode:
oder man hat ARC und dann klappt es einfach so ohne dieses Gedöns.
var
Foo : TFoo; FooIntf : IFoo; begin Foo := TFoo.Create; FooIntf := Foo; DoSomethingWithBar( Foo ); DoSomethingWithBaz( Foo ); end; |
AW: Fehlende Mehrfachvererbung bei Schnittstellen
Zitat:
Delphi-Quellcode:
ist und nicht wie im Beispiel oben von
TFoo
Delphi-Quellcode:
, worum es auch hier eigentlich geht.
IFoo
Ich kann dir nicht sagen, was C# da genau macht, wenn man ein IFoo an ein IBar oder IBaz übergibt (hab mir den IL Code nicht angeschaut). Aber dadurch, dass dort fest steht, "wenn IFoo implementiert wird, dann ist auch IBar und IBaz implementiert" ist sichergestellt, dass ein Cast von IFoo auf IBar oder IBaz immer erfolgreich ist. Und genau das geht in Delphi ebend nicht. Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:13 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