![]() |
AW: Versuche Objektorientierung zu lernen
Free heißt immer Free.
In Lazarus kann der Destructor und der Constructor auch anders heißen. Und schon hast du ein Problem, mit dem Verwenden von Destroy. |
AW: Versuche Objektorientierung zu lernen
Zitat:
Eine Instanz wird mit
Delphi-Quellcode:
ins Nirwana befördert.
Foo := TFoo.Create;
// something with Foo Foo.Free; Will man bei der Zerstörung der Klasse etwas spezielles ausführen, dann wir der Destructor überschrieben und der heißt nun mal
Delphi-Quellcode:
.
Destroy
Also man benutzt
Delphi-Quellcode:
und überschreibt
Free
Delphi-Quellcode:
!
Destroy
|
AW: Versuche Objektorientierung zu lernen
Zitat:
Delphi-Quellcode:
.
constructor
Dieser reserviert automatisch den Speicher. Wenn du keine weiteren Anforderungen an dein Objekt hast, dann brauchst du auch keinen speziellen
Delphi-Quellcode:
.
constructor
Delphi-Quellcode:
Allerdings musst du alles, was du in der Typ-Deklaration angibst auch ausformulieren (Ausnahme bei
type
TFoo = class public procedure DoSomething; end; ... procedure TFoo.DoSomething; begin // some code end;
Delphi-Quellcode:
)
virtual abstract
Delphi-Quellcode:
bedeutet, dass hier der Code aus der Ableitung ausgeführt werden soll.
inherited
Delphi-Quellcode:
Hier mal deine Unit2 korrekt formuliert:
type
TFoo = class public InFooObject : TObject; constructor Create; destructor Destroy; override; // ist in TObject als virtual deklariert, darum override end; ... constructor TFoo.Create; begin inherited; // den Code der Vorgänger-Klasse - hier TObject.Create - ausführen InFooObject := TObject.Create; end; destructor TFoo.Destroy; begin InFooObject.Free; inherited; // den Code aus der Vorgänger-Klasse - hier TObject.Destroy - ausführen end;
Delphi-Quellcode:
unit Unit2;
{$mode objfpc}{$H+} interface uses Classes, SysUtils; type TRechnen = class( TObject ) public // virtual - weil diese Methode in der Regel überschrieben werden soll // abstract - weil es keine Basis-Implementierung gibt, eben halt abstrakt :o) function CalcIt( a, b : real ) : real; virtual; abstract; end; TAddition = class( TRechnen ) public function CalcIt( a, b : real ) : real; override; end; TSubtraktion = class( TRechnen ) public function CalcIt( a, b : real ) : real; override; end; implementation function TAddition.CalcIt( a, b : real ) : real; begin result := a + b; end; function TSubtraktion.CalcIt( a, b : real ) : real; begin result := a - b; end; end. |
AW: Versuche Objektorientierung zu lernen
Wenn du keine weiteren Anforderungen an dein Objekt hast, dann brauchst du auch keinen speziellen constructor . // bedeutet? was sind "weitere Anforderungen?"
Ich zitier mich kurz mal selber, dass hatte ich vorhin noch hinzu editiert weil ich mir mit meinem Verständnis nicht sicher bin! Zitat:
Achso und danke jetzt funzts. Aber warum trat bei constructor create Eintrag nen Fehler auf? (sry dass ich euch gerade mit Fragen über Fragen bombardiere aber ich will dass bis Mitternacht durch haben soweit^^) |
AW: Versuche Objektorientierung zu lernen
Zitat:
Delphi-Quellcode:
type
TFoo = class private FData : integer; public constructor Create; property Data : integer read FData write FData; end; ... constructor TFoo.Create; begin inherited; // wir benötigen diesen constructor nur, weil wir FData mit dem Wert 10 initialisieren wollen FData := 10; end; Zitat:
Zitat:
Delphi-Quellcode:
Das meinte ich mit "Alles was du in der Typ-Deklaration angibst, musst du auch ausformulieren ...
type
TFoo = class public constructor Create; procedure DoSomething; end; ... // Das hier fehlte bei dir !!! constructor TFoo.Create; begin inherited; end; procedure TFoo.DoSomething; begin // some code end; Zitat:
|
AW: Versuche Objektorientierung zu lernen
Noch was zu constructor und inherited usw. Wenn du zum constructor nichts beizutragen hast, dann laß ihn weg, denn jede Klasse leitet sich von der Basisklasse TObject und erbt schon mal den constructor. Den hast du also schon. Dein
Delphi-Quellcode:
schadet zwar nicht, bringt aber auch nichts. Nötig wird es erst wenn du etwas dazu schreibst.
constructor TFoo.Create;
begin inherited; end; Nun zum inherited. So manches Mal stellt man sich die Frage ob er nötig ist, denn es gibt oft keinen Unterschied wenn man den wegläßt. Jetzt nicht hauen wenn es nicht stimmt, ist schon lange her wo ich es nach geguckt habe, aber bei Klassen auf der untersten Ebene ist nichts da was inherited aufrufen könnte. Deshalb könnte man sich die Frage stellen wozu der nötig ist. Nötig ist es spätestens da wenn man seine Klasse von einer anderen ableitet und die schon etwas in Create stehen hat. Dann, ohne inherited, wird der Part übergangen und die Klasse funktioniert nicht. Also am besten immer nutzen, ob nötig oder nicht. Dann geht es einem ins Blut über und man vergisst es nicht. |
AW: Versuche Objektorientierung zu lernen
Nicht Schaden?
Das
Delphi-Quellcode:
hat einen ganz bestimmten Grund, denn damit wird gesagt "führe die Methode des Vorfahren aus".
inherited
Wenn man etwas überschreibt, dann hat das meistens einen Grund. Oftmals möchte man zusäztliche Dinge machen, wobei das "zusätzlich" bedeutet, daß man das Alte auch haben will. Im Falle des Constructors, möchte man natürlich, daß die Teile der Vorfahren ebenfalls ordentlich initialisiert werden. :zwinker: PS: Es kann nicht schaden, wenn man das Inherited schreibt, auch wenn es keinen Vorfahren gibt ... dann läßt es der Compiler einfach weg. Es schadet aber oftmals, wenn man es vergißt, wenn es nötig wäre. Tipp: leite dir mal ein TMemo ab, überschreib den Constructor und vergiß das Inherited. Jetzt will ich mal sehn, wie du dich fragst "Wo ist mein Memo, ich seh ja garnichts?" und beim ersten Zugriff auf .Lines hoff' ich, du freust dich über die Exception. :roll: Ja, bei TObject fällt es nicht auf, da dort aktuell nur ein leerer Constructor vorhanden ist, aber wer weiß, ob da in Zukunft nicht doch mal irgendwas darin ist. :stupid: |
AW: Versuche Objektorientierung zu lernen
Mir ist gerade ein nettes Beispiel eingefallen, ich hoffe es ist gut.
Es zeigt, wie ich hoffe, gut wozu der constructor, aber vor allem inherited gut ist. Ich habe eine Klasse von TStringList abgeleitet und im constructor Create mit Wochentagen gefüllt. Wenn ich nun in der Prozedur Button1Click das Objekt erstelle und gleich mit ShowMessage anzeigen lasse, ist die Liste bereits mit Daten gefüllt. Ansonsten ist das eine normale StringList, ich kann also den Inhalt löschen oder bearbeiten. Aber als Unterschied zu StringList hatte sie am Anfang Daten drin. Nun mal ein kleines Experiment: mal in
Delphi-Quellcode:
inherited auskommentieren.
TWochenTageListe.Create
Was sehen wir? Eigentlich keinen Unterschied(²). In beiden Fällen wird beim Klick auf Button1 eine Liste ausgegeben. Ok, inherited wieder einsetzten und zum zweiten Beispiel unten gehen.
Delphi-Quellcode:
Das oben war eine Liste für Deutschland. In Bayern sagt man aber nicht Samstag, sondern Sonnabend. Wir erstellen nun eine extra Klasse für die Bayern, aber keine neue Liste, sondern leiten die WochenTageListe für Bayern aus der WochenTageListe für Deutschland ab und ändern lediglich den Samstag in Sonnabend. Da wir die Klasse ableiten, erben wir die Liste, allerdings nur wenn wir inherited aufrufen.
// --------- Eine Liste mit Wochentagen für Deutschland ----------------
// ----------------- Abgeleitet von TStringList ------------------------ type TWochenTageListe = class(TStringList) constructor Create; end; constructor TWochenTageListe.Create; begin inherited; // teste die Klasse mit inherited und ohne Add('Montag'); Add('Dienstag'); Add('Mittwoch'); Add('Donnerstag'); Add('Freitag'); Add('Samstag'); Add('Sonntag'); end; procedure TForm1.Button1Click(Sender: TObject); var slWochenTage: TWochenTageListe; begin slWochenTage := TWochenTageListe.Create; try ShowMessage(slWochenTage.Text); finally slWochenTage.Free; end; end; Wieder ein kleines Experiment: mal in
Delphi-Quellcode:
inherited auskommentieren.
TBayernWochenTageListe.Create
Was sehen wir? Nichts! Wenn wir auf Button2 klicken, ist die Liste leer. Nicht mal Sonnabend steht drin. Mit inherited wird die Wochentage Liste geerbt, ohne nicht.
Delphi-Quellcode:
Und noch ein letztes Experiment: wir setzen inherited nicht wie es soll am Anfang des constructors, sondern am Ende der Prozedur.
// ----------- Eine Liste mit Wochentagen für Bayern -------------------
// --------------- Abgeleitet von TWochenTageListe---------------------- type TBayernWochenTageListe = class(TWochenTageListe) constructor Create; end; constructor TBayernWochenTageListe.Create; var i: Integer; begin inherited; // teste die Klasse mit inherited und ohne for i := 0 to Count - 1 do if Self[i] = 'Samstag' then Self[i] := 'Sonnabend'; end; procedure TForm1.Button2Click(Sender: TObject); var slWochenTage: TBayernWochenTageListe; begin slWochenTage := TBayernWochenTageListe.Create; try ShowMessage(slWochenTage.Text); finally slWochenTage.Free; end; end; Was sehen wir? Eine Liste, aber kein Sonnabend, sondern Samstag. Als in der Schleife nach Samstag gesucht wurde, war die Liste noch nicht da.
Delphi-Quellcode:
constructor TBayernWochenTageListe.Create;
var i: Integer; begin //inherited; //Auskommentiert for i := 0 to Count - 1 do if Self[i] = 'Samstag' then Self[i] := 'Sonnabend'; inherited; // inherited am Ende end; ² - Damit meine ich keinen sichtbaren Unterschied in Bezug auf das Experiment. |
AW: Versuche Objektorientierung zu lernen
Vielen Dank an alle hat mir unglaublich geholfen.
:dp::dp::dp::dp::dp: PS.: Das Beispiel war super! :dp::dp::dp::dp::dp: |
AW: Versuche Objektorientierung zu lernen
Wobei man noch froh sein kann, daß beim Zugriff auf "Count" keine Exception auftrat, denn schließlich war zu diesem Zeitpunkt die Stingliste noch nicht initialisiert.
Daß keine Exception auftrat, liegt am Inneren der Count-Funktion, wo glücklicher Weise auf nichts "Schlimmes"/Kompliziertes zugegriffen wird. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:27 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