![]() |
Kind as Opa innerhalb der Deklerartion
Gibt es eine Möglichkeit eine Methode von Großvater bis Kind zu vererben... allerdings beim Kind die Methode vom Großvater direkt aufzurufen?
Hört sich vielleicht etwas konfus an, also hier der Code wie ich es gerne hätte:
Delphi-Quellcode:
Also bei mir kommt dann ein StackOverflow. Das würde ich gerne besser verstehen. Erwartet hätte ich vielleicht eine Zugriffsverletzung oder was anderes... aber StackOverflow verweundert mich schon ein wenig.
procedure TOpa.tuwas;
begin showmessage('Opa'); end; procedure TVater.tuwas; begin showmessage('Vater'); end; procedure TKind.tuwas; begin (self as TOpa).tuwas; end; |
Re: Kind as Opa innerhalb der Deklerartion
Hallo,
sag mal wie die Klassenherachie aufgebaut ist? Wie ist tuwas Deklariert (in der abstrakten Basis-Klasse)? |
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
Eine Möglichkeit die Funktion des Opas aufzurufen kenne ich nicht. Wenn es nur um den Vater ginge, ginge es mit inherited. |
Re: Kind as Opa innerhalb der Deklerartion
Der sohn ist vom Vater und der Vater vom Opa abgeleitet. Das ganze soll nur ein Beispiel sein und die Methode TuWas gibt nur eine MessageBox mit entweder dem Text 'Opa' (TOpa) oder 'Vater' (TVater) aus. Bei TKind sollte allerdings wieder 'Opa' ausgegeben werden.
procedure Tuwas; ist public deklariert Mit virtual, abstract usw. (wie heißen diese Schlüsselworte eigentlich?) kenn ich mich nicht mehr besonders gut aus und hab einfach nur herum probiert. Liegt es vielleicht an denen? Anwendungsbeispiele fallen mir momentan keine ein. Ich habe die Frage nur irgendwo einmal gelesen und dachte, dass man das vielleicht so implementieren könnte. Ich versuche mir OOP nach längerer Abstinz wieder besser ins Gehirn zu hämmern. Was gar nicht so leicht ist, weil mein bisheriges Wissen ein zur Hälfte vergessenes Halbwissen ist. Der Fehler tritt auch ohne override auf. Egal als was ich die Methode deklariere. Edit: Wo bleiben meine Marnieren... Herzlichen Dank natürlich!! |
Re: Kind as Opa innerhalb der Deklerartion
Hi,
Ich weiß nicht ob das geht.. entspricht evtl auch nicht dem Grundgedanken von OOP. Aber du könntest versuchen:
Delphi-Quellcode:
weiß allerdings nicht ob man inherited doppelt verwenden kann....
procedure TKind.tuwas;
begin inherited (inherited tuwas); end; |
Re: Kind as Opa innerhalb der Deklerartion
Auch bei TOpa(Kind).tuwas wird immer die überschiebene Methode aufgerufen, welche sich auf diesem Wege selber aufruft -> StackOverflow.
Mit "inherited" kommt man nur bis zu TVater zurück. Da bestände dann die Möglichkeit für "Sauereien" ala
Delphi-Quellcode:
Damit ruft ein inherited-Aufruf vom Kind über den Vater - Umweg die Opa-Methode auf. Nicht zu empfehlen da unübersichtlich und unflexibel.
if (Self is TKind) then
inherited else ShowMessage('Vater'); Die Möglichkeit das ganze zu umgehen wäre das verdecken der virtuellen Methode von TOpa (-> reintroduce;). Dadurch existieren die Methoden dann "nebeneinander" und der Aufruf gelingt. MfG, Dirk |
Re: Kind as Opa innerhalb der Deklerartion
Im Zweifelsfall musst du eben ein Parent-Feld einführen (und beim Create richtig belegen).
Sowas wie self.parent.parent.TuWas sollte auf jeden Fall gehen :stupid: |
Re: Kind as Opa innerhalb der Deklerartion
Delphi-Quellcode:
Geht leider nicht...zumindest nicht in der Form: Missing Operator or semicolon.
procedure TKind.tuwas;
begin inherited (inherited tuwas); end; Ihr habts einen Haufen interessanter Ideen! Vielen Dank an euch alle! |
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
Der richtige Weg wäre wohl eher eine Methode nicht so zu überschreiben das sie in der nachfolgenden Klasse nicht zu gebrauchen ist, oder noch besser auch TKind von TOpa abzuleiten. MfG, Dirk |
Re: Kind as Opa innerhalb der Deklerartion
Ich musste es mir auch erst wieder klar machen, aber es ist wie alle es sagen :mrgreen:
StackOverflow ist klar weil: Wenn du eine Klasse erstellst, werden ja alle Speicherbereich erstellt die so benötigt werden und eben auch die Ein-Sprungpunkte der Methoden der Klasse. Das Ermöglicht ja das LateBinding / SpäteBindung. D.h. erstmal das ja zum Zeitpunkt das Programmschreibens noch nicht klar ist, welche Methoden tatsächlich aufgerufen werden.
Delphi-Quellcode:
wird jetzt in Button2click ein Kind erstellt mit
var Person: TPerson;
//... procedure TForm1.Button1Click(Sender: TObject); begin Person.Tuwas; end;
Delphi-Quellcode:
muss ja irgend etwas dafür sorgen, dass bei Button1Click die richtige Methode aufgerufen wird. Wenn du also den Contructor von TKind aufrufst, wird eine Klasse erstellt die Identisch zu TPerson ist und als Einsprungpunkt für TuWas immer die Methode von TKind.Tuwas hat.
procedure TForm1.Button2Click(Sender: TObject);
begin Person := TKind.Create; end; Dieser Mechanismus erzeugt jetzt den Stackoverflow, denn egal welchen Typcast du auf Person außerhalb der Klassen anwendest - es wird immer TKind.Tuwas aufgerufen aufgrund des Einsprungpunktes. Das selbe gilt natürlich für innerhalb der Klassen. Somit kommt es in dein ursprünglicher Aufruf von (Self as TOpa).Tuwas zum Stackoverflow. Es ergibt sich eine Rekursion unendlicher Tiefe und der Stack läuft über wegen der Rücksprungadressen etc. Ich hoffe das hilft dir etwas beim Verständnis. Gruß, Chris [EDIT] 2x Button1Click :pale: [/EDIT] |
Re: Kind as Opa innerhalb der Deklerartion
Oja, das hilft!
Und damit hat die Frage sich wirklich ausgezahlt. Auch wenn sie in ihrer Ursprungsform irgendwie nicht so besonders sinnvoll erscheint. (Normal hätte ich einfach bei TVater eine weitere Methode eingeführt und nicht jene von TOpa überschrieben.) Manche Dinge versteht man erst richtig, wenn man ihre Grenzen findet. Achja, warum sind die Bezichnungen Opa, Vater und Kind ungünstig gewählt? Dachte nur, dass so der Stammbaum schnell ersichtlich ist. Bin aber was Namensgebung betrifft irgendwie sehr schleißig sollte ich ändern :wink: |
Re: Kind as Opa innerhalb der Deklerartion
Delphi-Quellcode:
TOpa = class
public procedure MeinName(); virtual; end; TVater = class( TOpa ) public procedure MeinName(); override; end; TKind = class( TVater ) public procedure MeinName(); override; end; ... procedure TForm1.FormCreate(Sender: TObject); var k: TKind; begin k := TKind.Create; k.MeinName; k.Free; end; { TOpa } procedure TOpa.MeinName; begin ShowMessage( 'Ich bin dein Opa' ); end; { TVater } procedure TVater.MeinName; begin inherited; ShowMessage( 'Ich bin dein Vater, krchh (:D)' ); end; { TKind } procedure TKind.MeinName; begin // inherited; asm call TOpa.MeinName end; ShowMessage( '(Kind:) a gugugugu' ); end; |
Re: Kind as Opa innerhalb der Deklerartion
Hey, das ist cool und funktioniert!
Wie bist Du auf die Idee gekommen und noch viel wichtiger: Warum geht das mit Inline-Assembler? Edit: Okay, ich kanns mir vorstellen warum. Angelegt wird die Methode ja irgendwo. Und mit call springt man halt zu eben jener. |
Re: Kind as Opa innerhalb der Deklerartion
Wie bin ich auf die Idee gekommen?
Hab einfach das Projekt debuggt, und gesehen, wie ein inherited Aufruf in Assembler aussieht. Warum funktioniert das? :firejump: MfG |
Re: Kind as Opa innerhalb der Deklerartion
@Aphton
Das funktioniert nicht! Greif mal in TOpa.MeinName auf self zu (Also lass dir irgendein sinnvolles Feld einfallen)! Ansonsten kannst du auch MeinName als Klassenmethode deklarieren, dann geht es auch ohne ASM. Edit: Aber eine Klassenmethode ist ja nicht das Ziel. Edit2: Folgende Änderung:
Delphi-Quellcode:
TOpa = class
private x:Integer; public procedure MeinName(); virtual; end; //und: procedure TOpa.MeinName; begin x:=5; ShowMessage( 'Ich bin dein Opa' ); end; procedure TKind.MeinName; var i:Integer; begin for i:=0 to 0 do showmessage('Damit es nicht durch Zufall doch klappt'); asm call TOpa.MeinName end; ShowMessage( '(Kind:) a gugugugu' ); end; |
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
|
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
|
Re: Kind as Opa innerhalb der Deklerartion
Nö, das tut es nicht.
Ich nehme mal an, per Inline Asm ruft man da direkt im Proc-Chain die Methode(Proc/Func) auf, da ja bei der Vererbung den erbenden Klassen alle Methoden der Parentklasse zur Verfügung stehen. Aber ich rate nur blöd rum... Deshalb halte ich mich an mein Avater :D MfG |
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
Und bei einer Klassenmethode gänge es auch ohne, ja. Aber hier ging es ja um virtuelle Methoden. |
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
|
Re: Kind as Opa innerhalb der Deklerartion
Habs getestet mit
Delphi-Quellcode:
Opa, Vater und Kind haben ein Unterschiedliches Alter. Wenn Alter eine Konstante ist geht es. Wenn nicht, dann ist Alter = 0. Das ist mir klar. Und natürlich die Limitation an dem ganzen. Wird ja nirgendwo zugewiesen. Und wenn dann würde es auch nix bringen, weil man ja auf die KLasse und nicht auf das Objekt zugreift. Hab ich das richtig verstanden?
TOpa = class
public alter : integer; procedure tuwas; end; procedure TOpa.tuwas; begin showmessage('Großvater '+inttostr(self.alter)); end; PS: Bin mal für einige Zeit weg... |
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
Edit: Ein mov eax,self dürfte allerindg schon reichen. Das sind aber reichlich Verrenkungen. |
Re: Kind as Opa innerhalb der Deklerartion
Hallo,
abgesehen von möglichen Designfehlern in der Klassenhierarchie - wäre es nicht am einfachsten, dem fleißigen Opa eine weitere, nicht-virtuelle Methode zu spendieren?
Delphi-Quellcode:
Die neue Methode kann in allen abgeleiteten Klassen direkt aufgerufen werden.
type
TOpa = class procedure TuWas; virtual; procedure OpaTutWas; end; procedure TOpa.TuWas; begin OpaTutWas; end; procedure TOpa.OpaTutWas; begin // die eigentlichen Aktionen end; [...] procedure TKind.TuWas; begin OpaTutWas; end; Gruß Hawkeye |
Re: Kind as Opa innerhalb der Deklerartion
Die Methode von Hawkeye219 funktioniert zwar,
aber wenn jetzt TOpa eine Klasse aus Delphi wie TMemo u.a. wäre, könnte man nicht einfach die Source ändern :wink: . Aber ich bin auch darauf gespannt, ob so was mit asm möglich ist. ALso so inetwa wie das hier:
Delphi-Quellcode:
asm
mov eax, self; call TOpa.MeinName; end; |
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
|
Re: Kind as Opa innerhalb der Deklerartion
Delphi-Quellcode:
:P
procedure TKind.MeinName;
var i:Integer; begin asm pushad end; for i:=0 to 0 do showmessage('Damit es nicht durch Zufall doch klappt'); asm popad call TOpa.MeinName end; ShowMessage( '(Kind:) a gugugugu' ); end; |
Re: Kind as Opa innerhalb der Deklerartion
Ich hab alles gelesen meine Frage war, ob durch dieses MOV danach auch die
Varaible self in TOpa.TuWas zu gebrauchen ist. :? |
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
|
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
Edit: Sorry, den hatte ich editiert.... :pale: @Aphton:
Delphi-Quellcode:
Aber mach doch, wie ich schon schrieb, ein mov eax,self direkt vor den Aufruf.
procedure TKind.MeinName;
var i:Integer; s:string; begin asm pushad end; s:='test'; for i:=0 to 0 do showmessage('Damit es nicht durch Zufall doch klappt'); asm popad call TOpa.MeinName end; ShowMessage( '(Kind:) a gugugugu' +s); end; |
Re: Kind as Opa innerhalb der Deklerartion
Etwas gekünstelt könnte man es so machen:
Delphi-Quellcode:
interface
type TOpa = class (TObject) public procedure SachWas (ARecurse : Integer = 0); virtual; end; TVater = class (TOpa) public procedure SachWas (ARecurse : Integer = 0); override; end; TSohn = class (TVater) public procedure SachWas (ARecurse : Integer = 0); override; end; implementation { TOpa } procedure TOpa.SachWas (ARecurse: Integer = 0); begin ShowMessage ('Hallo Jungs!') end; { TVater } procedure TVater.SachWas (ARecurse: Integer = 0); begin if ARecurse > 0 then inherited SachWas (ARecurse - 1) else ShowMessage ('Hallo Bub!') end; { TSohn } procedure TSohn.SachWas (ARecurse: Integer = 0); begin if ARecurse > 0 then inherited SachWas (ARecurse - 1) else ShowMessage ('GuGu!') end; procedure AlleSagenWas(Sender: TObject); var kind : TSohn; begin kind := TSohn.Create; try kind.SachWas; kind.SachWas(1); kind.SachWas(2); finally kind.Free; end; end; |
Re: Kind as Opa innerhalb der Deklerartion
AUA. :wall:
Wenn man sowas braucht, dann stimmt ganz einfach die Klassenhierarchie nicht. Hier gilt halt nicht TSohn ![]() |
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
Ich habe das auch noch nie gebraucht, aber es ist in mehreren anderen Programmiersprachen möglich. Warum soll denn hier grad Delphi der Maßstab sein (außer, dass wir hier in einem Delphi-Forum sind)? Ich gebe zu, dass mir diesbezüglich theoretisches Wissen fehlt. Ich würde diesen Fakt (da er des öfteren in Delphi-Foren auftaucht) nur mal geklärt wissen. Nicht, dass das einer mal behauptet hat und alle anderen plappern das nur nach. |
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
Zitat:
Code:
typedef Klassenname inherited; // oder base oder super oder ...
Zitat:
|
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
|
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
Ist aber auch egal, ob's die Sprache freiwillig hergibt oder per Assembler - bevor ich sowas mache, überleg ich mir nochmal, ob meine Klassenhierarchie stimmt. So, meine 2 Cent. :-D |
Re: Kind as Opa innerhalb der Deklerartion
Wenns den unbedingt sein muss ...
Delphi-Quellcode:
gehts auch ohne Assembler.
type
TOpa = class(TObject) private FAlter: Integer; public procedure SagWas; virtual; property Alter: Integer read FAlter write FAlter; end; TVater = class(TOpa) public procedure SagWas; override; end; TKind = class(TVater) public procedure SagWas; override; end; TSagWasProcedure = procedure (Self: Pointer); procedure TOpa.SagWas; begin showmessage(Format('Opa ist %d Jahre alt.', [Alter])); end; procedure TVater.SagWas; begin showmessage(Format('Vater ist %d Jahre alt.', [Alter])); end; procedure TKind.SagWas; var Proc: TSagWasProcedure; begin // showmessage(Format('Kind ist %d Jahre alt.', [Alter])); Proc := @TOpa.SagWas; Proc(Self); end; procedure TFTest.Button6Click(Sender: TObject); var K: TKind; begin K := TKind.Create; K.Alter := 10; K.SagWas; K.Free; end; |
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
Mit pusad "sichere" ich nur aus sicherheitsgründen die ganzen Register ... Man weiß ja nie, was zwischendrin so alles geschehen kann! MfG |
Re: Kind as Opa innerhalb der Deklerartion
Zitat:
Aber, wie gesagt, es geht mit ASM und ohne ASM, aber nicht ohne Tricksen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:29 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