![]() |
Zuweisung eines Methodenzeigers bei vererbten Interfaces
Hallo liebes Forum,
entschuldigt den etwas kryptischen Titel. Konnte die Frage iwie nicht prägnanter in einem Satz zusammenfassen... Ich habe folgendes Design, welches ich gerne benutzen würde:
Delphi-Quellcode:
Aufgabe, Frage, Diskussion ist jetzt die Zuweisung der Function factoryB() zur Methodenzeiger-Variable getInterfA.
IInterfA = interface(IInterface)
['{47B0ED79-41C2-4F2F-BA29-521D6B9872FB}'] function exec1(): string; end; IInterfB = interface(IInterfA) ['{47B0ED79-41C2-4F2F-BA29-521D6B9872FB}'] function exec2(): string; end; TImplB = class(TInterfacedObject,IInterfB) function exec1(): string; function exec2(): string; end; MInterfA = function(): IInterfA of object; MInterfB = function(): IInterfB of object; TForm1 = class(TForm) procedure FormCreate(Sender: TObject); public getInterfA: MInterfA; published function factoryB(): IInterfB; end; Eine Möglichkeit für die Zuweisung habe ich gefunden:
Delphi-Quellcode:
Geht die Zuweisung auch direkt, ohne die Variable lB und damit auch ohne Anlegen des Typs MInterfB?procedure TForm1.FormCreate(Sender: TObject); var lB: MInterfB; begin lB := self.factoryB; Self.getInterfA := MInterfA( lB ); ShowMessage(self.getInterfA.exec1()); end; function TForm1.factoryB: IInterfB; begin result := TImplB.create(); end; { TImplB } function TImplB.exec1: string; begin Result := 'Hello 1'; end; function TImplB.exec2: string; begin Result := 'Hello 2'; end; Das showmessage hat gemacht was es soll, aber tappe ich mit dem Design in iwelche Fallen? Gibt es Situation, in denen dieser Downcast Probleme macht? Ist es überhaupt gutes Design? Wie könnte man es eleganter lösen? Dank und Gruß |
AW: Zuweisung eines Methodenzeigers bei vererbten Interfaces
Warum nicht einfach
Delphi-Quellcode:
Oder habe ich dein Problem falsch verstanden?
procedure TForm1.FormCreate(Sender: TObject);
var lB: MInterfB; begin ShowMessage(factoryB.exec1); (* lB := self.factoryB; Self.getInterfA := MInterfA( lB ); ShowMessage(self.getInterfA.exec1()); *); end; |
AW: Zuweisung eines Methodenzeigers bei vererbten Interfaces
Zitat:
|
AW: Zuweisung eines Methodenzeigers bei vererbten Interfaces
Verstehe ich richtig, dass Du prüfen willst, ob Dein Objekt nicht nur IInterfB sondern auch IInterfA unterstützt?
Dann ginge das vielleicht so:
Delphi-Quellcode:
Das geht mit jedem Interface, unabhängig davon, ob es sich um Ableitungen handelt oder nicht.
TImplB = class(TInterfacedObject, IInterfB, IInterfA)
... var lA: IInterfA; if Supports(lB, IInterfB, lA) then DoSomething(lA); |
AW: Zuweisung eines Methodenzeigers bei vererbten Interfaces
Zitat:
Delphi-Quellcode:
unterscheidet sich von
MInterfA = function(): IInterfA of object;
Delphi-Quellcode:
ja nur durch einen "Downcast". Meiner Meinung eine gültige Zuweisung, bzw. ein legitimes Design.
function factoryB(): IInterfB;
Der Compiler lässt mich keine direkte Zuweisung machen:
Delphi-Quellcode:
Dafür könnte es ja Gründe geben, die ich nicht verstehe/kenne, aber gerne wissen würde. Daher meine Fragen nach der einfachsten Art der Zuweisung und ob es Argumente gibt, dies nicht zu tun, bzw was dabei zu beachten ist.
Self.getInterfA := self.factoryB;
|
AW: Zuweisung eines Methodenzeigers bei vererbten Interfaces
Zitat:
Delphi-Quellcode:
TImplB = class(TInterfacedObject, IInterfB, IInterfA)
IInterfA wird nicht automatisch unterstützt, nur weil IInterfB davon abgeleitet ist. Du musst dieses also explizit zusätzlich angeben. Dann solltest Du auf Deine Methoden (die ich nicht wirklich verstehe, zumal die Implementierungen im Beispiel fehlen) verzichten können. |
AW: Zuweisung eines Methodenzeigers bei vererbten Interfaces
Nur zum Verständnis: Aus dem Feld "getInterfA: MInterfA;" was sich wie eine Methode anhört (wegen dem get), eine echte Methode zu machen, ist in deinem Fall keine Lösung?
|
AW: Zuweisung eines Methodenzeigers bei vererbten Interfaces
Im Endeffekt geht es dir doch um Kovarianz für Rückgabewerte, oder? Interfaces an sich haben damit eigentlich gar nichts zu tun. Du willst dass ein Methodenzeiger auf eine "Formenfabrik"-Methode auf eine "Kreisfabrik"-Methode oder eine "Trapezfabrik"-Methode beinhalten kann.
Vereinfachtes Beispiel:
Delphi-Quellcode:
program Project19;
uses System.SysUtils; type TBase = class(TObject); TSub = class(TBase); function createBase(): TBase; begin Result := TBase.Create(); end; function createSub(): TSub; begin Result := TSub.Create(); end; var baseFactory: TFunc<TBase>; subFactory: TFunc<TSub>; begin baseFactory := createBase; //baseFactory := createSub; // E2010, kann Delphi nicht subFactory := createSub; //subFactory := createBase; // E2010, war zu erwarten end. Das geht in Delphi nicht, Delphi kann keine Kovarianz für Rückgabetypen. Ebenfalls leider nicht für z.B. Var-parameter. Der erste QC-Eintrag sogar schon aus 2005 ;-) ![]() Sprachen wie Java z.B. können es: ![]() |
AW: Zuweisung eines Methodenzeigers bei vererbten Interfaces
Zitat:
Hm, könnte evt ein Workaround sein... In der Praxis ist die Variable getInterfA: MInterfA; nicht im selben Objekt wie die function factoryB(): IInterfB; dh ich brauche schon mal ieinen Datentyp um factoryB() an andere Teile zu übergeben, aber man könnte natürlich eine Methode in Form1 deklarieren, die den Cast macht:
Delphi-Quellcode:
damit könnte ich mir den Typ MInterfB schon mal sparen... Könnte schöner/sauberer als meine Lösung oben sein !?
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject); public getInterfA: MInterfA; published function factoryACast(): IInterfA; function factoryB(): IInterfB; end; implementation procedure TForm1.FormCreate(Sender: TObject); begin Self.getInterfA := Self.factoryACast; ShowMessage(self.getInterfA.exec1()); end; function TForm1.factoryACast: IInterfA; begin Result := self.factoryB(); end; function TForm1.factoryB: IInterfB; begin result := TImplB.create(); end; Trotzdem würden mich obigen Fragen weiterhin interessieren ... Zitat:
|
AW: Zuweisung eines Methodenzeigers bei vererbten Interfaces
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:28 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 by Thomas Breitkreuz