![]() |
Zuweisung in einer anderen Klasse
Hallo,
beispielhaft folgenden Sourcecode:
Delphi-Quellcode:
TClassA = class (TObject)
ValueA : String; function print (): String; end; TClassB = class (TClassA) ValueB : string; function print () : string ; overload; end;
Delphi-Quellcode:
Wie wird die Zuweisung in der letzten Zeile möglich? Die Klasse B beinhaltet doch alles was A auch kann. Was habe ich vergessen?
A:= TClassA.Create;
a.ValueA := 'Class A'; B:= TClassB.Create; b := a; <--- Warum ist diese Zuweisung nicht möglich |
Re: Zuweisung in einer anderen Klasse
Was für ein Typ hat b?
Ich glaube <Object>.Assign() wäre hier besser |
Re: Zuweisung in einer anderen Klasse
Da TClassB von TClassA erbt, kann zwar jedes Objekt der Klasse A in eines der Klasse B gecastet werden, umgekehrt gesht das aber nicht.
Wenn beide Klassen die gleiche Funktionalität haben sollen, und austauschbar sein sollen, wäre eine abstrakte Basisklasse oder ein Interface besser geeignet ;) @mkinzer: Zitat:
|
Re: Zuweisung in einer anderen Klasse
B ist vom Typ TClassB. Mit Assign werden die Werte kopiert und nicht die Referenz?
|
Re: Zuweisung in einer anderen Klasse
Zitat:
Zitat:
Der Typ steht aber nirgends |
Re: Zuweisung in einer anderen Klasse
Delphi-Quellcode:
B ist zwar Nachfahre von A, aber da B als Nachfahre unter Umständen neue/zusätzliche Funktionalitäten besitzen kan, ist es nur andersrum möglich
b := a; <--- Warum ist diese Zuweisung nicht möglich
also A := B; geht, da der Typ A alle Funktionen enthält, welche B auch hat. PS:
Delphi-Quellcode:
hier wäre wohl Virtual+Override angebracht
B := TClassB.Create;
B.Print > TClassB.Print A := B; A.Print > TClassA.Print A := TClassB.Create; A.Print > TClassA.Print
Delphi-Quellcode:
hierzu wurde zwar schon etwas gesagt, aber es wurde eventuell nicht klar erwähnt, daß du hiermit ein MemoryLeak erstellst
B := TClassB.Create;
B := A; eine Instanz von TClassB wird erstellt und dann der Instanzvariable B eine andere Instanz zugewiesen, wobei die erstellte Instanz dann frei im Programm rumschwirrt und nicht freigegeben wird. |
Re: Zuweisung in einer anderen Klasse
Es sollte nur ein Beispiel sein, wie ich eine bestehende Klasse erweitere. Und ich würde sie gerne über Vererbung erweitern.
Folgendes funktioniert :
Delphi-Quellcode:
Wobei nach
var
a : TClassA; b : TClassB; begin a:= TClassA.Create; a.ValueA := 'Class A'; // b:= TClassB.Create; b := TClassB(a); b.ValueB := 'Class B'; mmo1.Lines.Add(b.print); mmo1.Lines.Add(a.print); end;
Delphi-Quellcode:
alle zuvor vorhandenen Inhalte in b zurückgesetzt wurden.
b := TClassB(a);
Noch die beiden Print Methoden:
Delphi-Quellcode:
{ TClassA }
function TClassA.print: String; begin Result := self.ValueA; end; { TClassB } function TClassB.print: string; begin Result := inherited print() + self.ValueB; end; |
Re: Zuweisung in einer anderen Klasse
Du solltest dich dringend mit Objekten und deren Verwendung beschäftigen.
Delphi-Quellcode:
Ist ein harter TypCast, also man tut so, als wenn A vom Typ TClassB wäre
b := TClassB(a);
und erstellt damit keine Kopie!
Delphi-Quellcode:
TClassA = class (TObject)
ValueA : String; function Print : String; virtual; procedure Assign(O: TObject); virtual; end; TClassB = class (TClassA) ValueB : String; function Print : String; override; procedure Assign(O: TObject); override; end; function TClassA.Print : String; begin Result := ValueA; end; procedure TClassA.Assign(O: TObject); begin if O is TClassA then ValueA := TClassA(O).ValueA; end; function TClassB.Print : String; begin Result := inherited + ValueB; end; procedure TClassA.Assign(O: TObject); begin inherited; if O is TClassB then ValueB := TClassB(O).ValueB; end;
Delphi-Quellcode:
Wenn für Objekte vom Typ TClassB immer nur Variablen mit diesem Typ verwendet werden und genauso bei TClassA, dann könnte man auch virtual weglassen und statt override ein reintroduce nehmen.
var
a : TClassA; b : TClassB; begin a := TClassA.Create; a.ValueA := 'Class A'; b := TClassB.Create; b.Assign(a); b.ValueB := 'Class B'; Memo1.Lines.Add(b.Print); Memo1.Lines.Add(a.Print); end; PS: Overload ist bei dir falsch genutzt und du müßtes Reintroduce verwenden, da du Funktionen verdeckst und nicht "mit anderen Parametern" überlädst. |
Re: Zuweisung in einer anderen Klasse
Hallo martin_
mir scheint, dir ist nicht ganz klar was da passiert. Ich habe deinen Code mal leicht verändert und versucht zu kommentieren, was da "hinter der Bühne" passiert:
Delphi-Quellcode:
Probier mal beide Varianten aus und lass dich überraschen, was heraus kommt.
type
TClassA = class (TObject) public ValueA : Integer; function Print : AnsiString; virtual; end; TClassB = class (TClassA) public ValueB : Integer; ValueC : Integer; function Print : AnsiString; override; function PrintEx : AnsiString; end; implementation { TClassA } function TClassA.Print: AnsiString; begin Result := IntToStr(ValueA); end; { TClassB } function TClassB.Print: AnsiString; begin Result := Format ('%d, %d, %d', [ValueA, ValueB, ValueC]); end; function TClassB.PrintEx: AnsiString; begin Result := Format ('%d, %d, %d', [ValueA, ValueB, ValueC]); end; { Aufruf } procedure Test; var A : TClassA; { Das hier ist ein Pointer auf eine Datenstruktur der Klasse TClassA } B : TClassB; { Das hier ist ein Pointer auf eine Datenstruktur der Klasse TClassB } begin { Variante A } A := TClassA.Create; { Hier wird eine Instanz der Klasse TClassA erzeugt. D.h., es wird soviel Speicher alloziert, wie eine solche Instanz braucht, und der Zeiger A zeigt auf diese Daten. } { Variante B } // A := TClassB.Create; { Im Vergleich dazu wird hier eine Instanz von TClassB erzeugt und nur als eine vom Typ TClassA betrachtet. Das ist korrekt, da TClassB von TClassA abgeleitet ist. } A.ValueA := TClassA.InstanceSize; { Speichere die Größe der Klasseninstanz von TClassA in ValueA } B := TClassB(A); { Hier sagst du Delphi, dass der Pointer B auf dieselbe Adresse zeigen soll wie A. Außerdem soll die dort liegende Struktur als eine vom Typ TClassB betrachtet werden, egal ob die beiden kompatibel sind. Das wird [i]mindestens[/i] zu unerwarteten Ergebnissen führen. } B.ValueB := TClassB.InstanceSize; { Speichere die Größe der Klasseninstanz von TClassA in ValueB } { Hier wird in der virtuellen Methodentabelle nachgesehen, welche Methode aufgerufen werden soll. Im Fall der Variante A ist das TClassA.Print. } ShowMessage (B.Print); { Hier wird im Fall der Variante A auf eine Methode zugegriffen, die es in der Methodentabelle von TClassA gar nicht gibt! Wenn das nicht scheppert, ist es eher Zufall. } ShowMessage (B.PrintEx); end; |
Re: Zuweisung in einer anderen Klasse
Zitat:
Zitat:
Wird nach dieser Stelle
Delphi-Quellcode:
im Code nachgefragt, ob
B := TClassB(A);
Delphi-Quellcode:
so trifft es zu. Mir fehlt da das Verständnis zwischen override und reintroduce;
B is TClassB
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 09: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 by Thomas Breitkreuz