![]() |
Polymorphie bei Methodenrückgabewerten
Guten Morgen alle zusammen :nerd: ,
ich arbeite momentan sehr viel mit Objekten und COM Interfaces. Da ich mir als Ziel gesetzt habe, wirlich sauberes OOP zumachen gibt es einige Probleme. Der Compiler macht nicht mit, genauer er erkennt die Polymorphie nicht. Folgenes Beispiel: Objekt A besitzt die virtuelle abstrakte Methode XYZ, die das Interface C zurück gibt. Objekt B, abgeleitet von Objekt A, überschreib die Methode XYZ, gibt allerdings Interface D, welches von Interface C abgeleitet ist zurück. In meinen Augen ist das keine Verletzung der Regeln, da Interface D auch ein vollwertiges Interface C ist. Somit gibt die Funktion XYZ immer ein Interface C zurück, allerdings manchmal mehr als nur C. Trozdem beschwert sich der Compiler: "There is no method in an ancestor to override". Ich habe das Problem jetzt mit reintroduce "gelöst", bzw. rein gewaschen, wirlich sauber ist das ja nicht, eine Methode einer zu streichen und was anderes hinschreiben, das ähnelt eher dem Overload als einer abstrakten Vererbung. Fehlende "virtual"- oder "abstract"-Statements habe ich mehrmals ausgeschlossen. Gibt es da wirklich keine Möglichkeit? Mit ordinalen Typen geht es ja auch, warum also nicht mit Interfaces und Classes, die im Prizip auch nur ordinal sind ( Pointer afaik ). Für die, die den Beweis brauchen: :wink:
Delphi-Quellcode:
Naja hoffentlich gibts eine schöne Lösung, denn Code muss nicht nur funktionieren, Code muss gut aussehen, Code muss eine Persönlichkeit haben, Code muss Leben & Atmen... ^^
type
TSubKlasse = class(TObject); TTopKlasse = class(TSubKlasse); TElternKlasse = class(TObject) public function Test : TSubKlasse; virtual; abstract; end; TKind1Klasse = class(TElternKlasse) public // TTopKlasse ist ein TSubKlasse, also gültig. function Test : TTopKlasse; override; end; TKind2Klasse = class(TElternKlasse) public // So gehts auch, mit brachialer Überschreibgewalt. function Test : TTopKlasse; reintroduce; end; TKind3Klasse = class(TElternKlasse) public // Allerdings auch so, was nicht OOP ist. function Test(Param1 : Integer) : TTopKlasse; reintroduce; end; Gute Nacht! xD |
Re: Polymorphie bei Methodenrückgabewerten
Wenn TTopKlasse wirklich kein direkter Nachfahre von TObject ist, dann ist das (sowieso) nicht Polymorphie, sondern Varianz ;) Und soweit ich das erkenne, unterstützt Delphi das nicht. Du musst immer mit exakter Signatur überschreiben.
|
Re: Polymorphie bei Methodenrückgabewerten
Wenn die Methode anders deklariert ist als in der Elternklasse, dann kannst du die der Elternklasse damit nicht überschreiben. Überschreiben bedeutet wirklich eine gleiche Deklaration. Denn das Ziel ist ja, über eine Variable vom Typ der Elternklasse mit einem Objekt vom Typ der abgeleiteten Klasse direkt die Methode aufrufen zu können.
Das geht aber nicht, wenn diese anders deklariert ist. Das ist nicht der Sinn des Überschreibens und damit nicht möglich. Mehrere gleichlautende Methoden werden überladen oder müssen neu eingeführt werden, anders geht es nicht. Wenn du genauer sagen würdest worum es geht, dann könnte vielleicht jemand eine andere saubere OOP Lösung vorschlagen. Dein Quelltextbeispiel ist etwas anders gelagert, oder? Oder geht es dir auch mit den Interfaces um verschieden deklarierte Methoden? |
Re: Polymorphie bei Methodenrückgabewerten
Zitat:
Deine Rückgabewerte sind unterschiedlich, also warum so eine Aufregung? Zielorientierte Frage an Dich, was willst Du denn genau nun umsetzen? Der Sinn von virtual und override ist Dir schon klar, oder? Dein Beispiel hat mit Polymorphie leider überhaupt nix zu tun. |
Re: Polymorphie bei Methodenrückgabewerten
@stoxx & jaenicke: In der Theorie ist das kein Problem, Dax hat es ja schon angesprochen: Rückgabetypen sind
![]()
Delphi-Quellcode:
heißen sollte)
TTopKlasse = class(TSubKlasse); // Merkwürdige Bezeichner ;)
@Desmulator: Das einfachste wird es sein, in den abgeleiteten Klassen eine TestEx-Methode einzuführen, die dann das abgeleitete Interface zurückgibt. Im überschriebenen Test kannst du dann einfach TestEx zurückgeben. Gut, wenn du diese Klasse dann nochmal ableiten willst, wird es langsam hässlich :stupid: . |
Re: Polymorphie bei Methodenrückgabewerten
Danke für die Antworten,
es handelt sich wirklich um einen "Tippfehler", wie Khabarakh vermuted hatte. Ich habe es korrigiert. Die Bezeichner sollen ja nur den Sachverhalt darstellen. :D Ich habe nochmal genau nachgeschaut, das Problem stellt sich nur bei vererbten Interfaces. Beispiel :
Delphi-Quellcode:
program Project1;
{ $mode objfpc}{ $H+} type ISubKlasse = interface(IInterface) end; ITopKlasse = interface(ISubKlasse) end; TSubKlasse = class(TInterfacedObject, ISubKlasse); TTopKlasse = class(TSubKlasse, ITopKlasse); TElternKlasse = class(TObject) public function Test : TSubKlasse; virtual; function Test2 : ISubKlasse; virtual; end; TKind1Klasse = class(TElternKlasse) public // TTopKlasse ist ein TSubKlasse, also gültig. function Test : TTopKlasse; override; function Test2 : ITopKlasse; override; // Diese Zeile wir bestraft mit der Meldung: // project1.lpr(22,14) Error: There is no method in an ancestor class to be overridden: "TKind1Klasse.Test2:ITopKlasse" end; TKind2Klasse = class(TElternKlasse) public // So gehts auch, mit brachialer Überschreibgewalt. function Test : TTopKlasse; reintroduce; function Test2 : ITopKlasse; reintroduce; end; function TElternKlasse.Test : TSubKlasse; begin Result := TSubKlasse.Create(); end; function TKind1Klasse.Test : TTopKlasse; begin Result := TTopKlasse.Create(); end; function TKind2Klasse.Test : TTopKlasse; begin Result := TTopKlasse.Create(); end; function TElternKlasse.Test2 : ISubKlasse; begin Result := ISubKlasse(Test); end; function TKind1Klasse.Test2 : ITopKlasse; begin Result := ITopKlasse(Test); end; function TKind2Klasse.Test2 : ITopKlasse; begin Result := ITopKlasse(Test); end; begin end. |
Re: Polymorphie bei Methodenrückgabewerten
Mit Klassen klappt das so? Das hätte ich nicht gedacht, das muss ich direkt einmal ausprobieren. Ich dachte die Deklaration müsste exakt übereinstimmen.
Dass es einen Unterschied zwischen Klassen und Interfaces gibt, wäre allerdings an der Stelle seltsam. Ich probiere es einmal aus. // EDIT: Mit welcher Delphiversion klappt das denn bei dir? ich bekomme selbst mit der neuesten Version 2009 einen Fehler in beiden Zeilen: Zitat:
|
Re: Polymorphie bei Methodenrückgabewerten
Ich nutze Lazarus mit FreePascal 2.0.2 im objfpc-mode, aber auch im delphi-mode funktioniert es. Kontrollier mal deine CompilerEinstellungen, ich meine zu wissen, aus meinen alten delphi zeiten, dass man da irgendwas einstellen kann. In der nähe wo es auch die StackOverflow Prüfung zum ein und ausschalten gibt uws.
Nun mit "normalen" Typen sollte es aber gehen.
Delphi-Quellcode:
TInteger1 = Integer; TInteger2 = TInteger1; TElternKlasse = class(TObject) public ... function Test3 : TInteger1; virtual; abstract; // Absract oder nicht, spielt keine Rolle. end; TKind1Klasse = class(TElternKlasse) public ... function Test3 : TInteger2; override; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08: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