![]() |
Vererbung: Wie rufe ich Klasse.Parent.Methode auf?
Hallo,
ich habe ein Problem mit einem Methodenaufruf. Folgendes Szenario:
Delphi-Quellcode:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Memo1: TMemo; Button1: TButton; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; TMutter = class(TObject) public procedure a(x: Boolean); virtual; procedure b; virtual; end; TKind = class(TMutter) public procedure a(x: Boolean); override; procedure b; override; end; procedure Log(s:string); var Form1: TForm1; implementation {$R *.dfm} procedure Log(s:string); begin Form1.Memo1.Lines.Add(s); end; procedure TForm1.Button1Click(Sender: TObject); var Mutter: TMutter; Kind: TKind; begin Memo1.Lines.Clear; Log(''); Log('Mutter beinhaltet Mutter'); Mutter := TMutter.Create; Mutter.a(True); // TMutter.a wird aufgerufen Mutter.Free; Log(''); Log('Kind beinhaltet Kind'); Kind := TKind.Create; // TKind.a wird aufgerufen Kind.a(True); Kind.Free; Log(''); Log('Mutter beinhaltet Kind'); Mutter := TKind.Create; Mutter.a(False); // TKind.a wird aufgerufen Mutter.Free; end; { TKind } procedure TKind.a(x: Boolean); begin Log('TKind.a1'); inherited; Log('TKind.a2'); end; procedure TKind.b; begin Log('TKind.b1'); inherited; Log('TKind.b2'); end; { TMutter } procedure TMutter.a(x: Boolean); begin Log('TMutter.a1'); if x then begin // b aufrufen. (Wenn Self = TKind ist, dann wird TKind.b aufgerufen.) b; end else begin // Hier sollte immer TMutter.b aufgerufen werden!!! b; end; Log('TMutter.a2'); end; procedure TMutter.b; begin Log('TMutter.b'); end; end. Bei
Delphi-Quellcode:
wird z.B. folgendes Aufgerufen:
Log('Mutter beinhaltet Kind');
So eine einfache Lösung wie
Delphi-Quellcode:
funktionieren natürlich nicht. ;-)
TMutter(Self).b
Hat jemand eine Idee? Ich denke imMoment darüber nach mit den Methoden Pointer zu ermitteln und die Methode über die Adresse direkt aufzurufen. Aber das muß auch einfacher gehen. Danke im Voraus. MaBuSE |
AW: Vererbung: Wie rufe ich Klasse.Parent.Methode auf?
Zitat:
Delphi-Quellcode:
TMutter = class(TObject)
protected procedure InternalB; public procedure a(x: Boolean); virtual; procedure b; virtual; end; procedure TMutter.a(x: Boolean); begin Log('TMutter.a1'); if x then begin // b aufrufen. (Wenn Self = TKind ist, dann wird TKind.b aufgerufen.) b; end else begin // Hier sollte immer TMutter.b aufgerufen werden!!! InternalB; end; Log('TMutter.a2'); end; procedure TMutter.InternalB; begin Log('TMutter.b'); end; procedure TMutter.b; begin InternalB; end; |
AW: Vererbung: Wie rufe ich Klasse.Parent.Methode auf?
Hallo Mabuse,
wenn du alle Quellen in der Hand hast (Mutter & Kind) und wir hier nicht über Sinn & Unsinn deiner Forderung reden wollen :-D dann mach
Delphi-Quellcode:
OHNE
TMutter.b;
Delphi-Quellcode:
und dementsprechend
virtual
Delphi-Quellcode:
ohne
TKind.b;
Delphi-Quellcode:
. Dein Problem ist ja eben die VMT die eb en genau dafür sorgen soll, dass nur die Methoden aufgerufen werden die auch wirklich zu dem drinne Steckenden gehören. Also ohne VMT arbeiten und die Methoden überdecken und in den Sourcen selber entscheiden was aufgerufen werden soll aufgrund dessen was man ist.
override
Sollte eigentlich gehen. Gruß, Chris |
AW: Vererbung: Wie rufe ich Klasse.Parent.Methode auf?
Habe den Source mal angepasst. Nicht schön aber sollte gehen...
Zitat:
|
AW: Vererbung: Wie rufe ich Klasse.Parent.Methode auf?
Zitat:
Zitat:
@Uwe: Stimmt, auf die Idee bin ich gar nicht gekommen. Ich probier das mal aus. Danke. @Chris: Das geht leider nicht, da ich das alte Verhalten ja durchaus wünsche, wenn (True) übergeben wurde. Außerdem sollte man wenn man es so macht das Schlüsselwort reintreduce verwenden um zu dokumentieren, dass man genau das machen möchte und nicht aus versehen virtual/override vergessen hat. Danke für die Antworten |
AW: Vererbung: Wie rufe ich Klasse.Parent.Methode auf?
Ich denke du solltest dir mal das
![]() Verkürzt gesagt muss es jederzeit möglich sein an eine Klasse durch eine davon abgeleitete Klasse zu ersetzen.
Delphi-Quellcode:
Dies ist auch der Grund dafür weshalb man in abgleiteten Klassen keine Properties oder Methoden entfernen kann.
// der Procedure muss es egal sein ob "myobject" vom Typ TBasisKlasse oder von einer davon abgeleiteten Klasse ist
procedure Machwas(TBasisKlasse: myobject); begin Auch darf man die Sichtbarkeit (z.B. von public auf private) nicht einschränken. Das Überdecken einer virtuellen Methode mit
Delphi-Quellcode:
ist ein ganz klares Pfui.
reintroduce
Häufig lassen sich Designprobleme lösen indem man virtuelle Methoden nicht public sondern nur protected macht:
Delphi-Quellcode:
Diese Vorgehensweise ist auch als
TBaseclass = class(TObject)
protected procedure Internal_A(x: Boolean); virtual; public procedure A(x: Boolean); ... procedure TBaseclass.A(x: Boolean); begin // code vorher // die Basisklasse kann hier sogar entscheiden ob sie Internal_A() überhaupt aufrufen möchte Internal_A(x); // virtuelle Methode aufrufen // code danach (Exceptionhandling, Logging, was auch immer) end; ![]() |
AW: Vererbung: Wie rufe ich Klasse.Parent.Methode auf?
Hallo MaBuSE,
Zitat:
Delphi-Quellcode:
bin ich zu 100% bei dir. Der Quelltext funktioniert aber tatsächlich, wenn du es so machst - zumindest bei mir XE5.
reintroduce
Delphi-Quellcode:
Oder is dir das zu explizit?
TMutter = class(TObject)
public procedure a(x: Boolean); virtual; procedure b; end; TKind = class(TMutter) public procedure a(x: Boolean); override; procedure b;reintroduce; end; //.... procedure TMutter.a(x: Boolean); begin Log('TMutter.a1'); if x then begin // b aufrufen. (Wenn Self = TKind ist, dann wird TKind.b aufgerufen.) TKind(Self).b; end else begin // Hier sollte immer TMutter.b aufgerufen werden!!! TMutter(Self).b; end; Log('TMutter.a2'); end; Gruß, Chris |
AW: Vererbung: Wie rufe ich Klasse.Parent.Methode auf?
Zitat:
Ich bin Fan von KISS ("keep it stupid simple" oder "So einfach wie möglich, so kompliziert wie nötig") Die Lösung mit dem internal_procname finde ich gut. Sie ist vor allem einfacher zu verstehen, wenn man in ein paar Jahren noch mal über die Zeilen stolpert. Internal_procname hatte ich schon in den protected Abschnitt gesetzt, bevor ich die Nachricht von sx2008 las. Ich habe das mit dem internal_procname auch schon früher gemacht, aber aus irgendeinem Grund habe ich mich diesmal in dem Problem festgefahren. Man sieht den Wald vor lauter Bäumen nicht. Normalerweise finde ich die Lösung dann beim Erstellen des Beispielprogramms, diesmal nicht :stupid: Da ist es gut, wenn man von der DP einen Schups in die richtige Richtung bekommt. :dp: Danke für alle Antworten. MaBuSE |
AW: Vererbung: Wie rufe ich Klasse.Parent.Methode auf?
Zitat:
1. Woher soll die Mutter wissen, das es ein Kind gibt? 2. Welche Methode soll aufgerufen werden, wenn es noch eine Ableitung der TMutter (oder von TKind) gibt? 3. Wenn die Mutter wissen muss, das es genau das eine Kind gibt, wozu dann zwei Klassen? Mach es so, wie Uwe vorgeschlagen hat. Die Mutter ruft entweder explizit die eigene Methode oder aber die virtuelle Methode auf. So ist es OOP-konform und auch sauber. |
AW: Vererbung: Wie rufe ich Klasse.Parent.Methode auf?
Zitat:
Delphi-Quellcode:
...
if Self is TKind then (Self as TKind).b; ... Zitat:
Da sie ja nicht mit reintreduce überschrieben wurde. Zitat:
Delphi-Quellcode:
Aber wahrscheinlich gibt es dafür auch einen einfacheren Weg.
...
if Self is TLieblingsKind then begin (Self as TLieblingsKind).b end else begin if Self is TStiefKind then begin (Self as TStiefKind).b end else begin // Mutterschaftstest durchführen. // Den Vorteil, den Mütter haben ist, // das sie in der Regel wissen, dass es ihre Kinder sind. end; end; ... Fakt ist, das die Mutter alle Kinder (und Kindes-Kinder), die eine Sonderbehandlung benötigen, kennen muss. Das icht schlecht. Das ist bei der internal_proc Lösung nicht der Fall. Zitat:
Wenn du meine Texte gelesen hättest, wüsstest Du wie ich darüber denke. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:31 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