![]() |
Delphi-Version: 5
liege ich richtig mit dem OOP-Versuch
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen, ich bin in Fragen OOP noch nicht so sicher und bitte um eine Meinungsäußerung, ob ich mit einem kleinen Testprogramm richtig liege.
Es handelt sich um eine einfache Flächenberechnung als Beispiel. Mir geht es in erster Linie darum, ob ich die Getter und Setter sowie die propertys richtig eingesetzt habe und ob man noch mehr in private verstecken könnte. Darauf würde ich dann aufbauen, um meine Möglichkeiten zu erweitern. Ein Ok würde auch genügen. Danke |
AW: liege ich richtig mit dem OOP-Versuch
Die Methoden auf welche die Properties zugreifen müssen nicht public sein, die können auch private oder protected sein.
|
AW: liege ich richtig mit dem OOP-Versuch
Hallo
Es ist eine ganz schlechte Idee den Destructor Free zu nennen. Free ist eine Methode von TObject die überprüft ob Self <> nil ist und dann den destructor Destroy aufruft. Benenne Deinen Destructor um zu: Interface
Delphi-Quellcode:
destructor Destroy; override;
Implementation
Delphi-Quellcode:
Dein Code ruft sich selber auf in Deinem destructor Free!!!
destructor TFlaecheninh.Destroy;
begin inherited Destroy; end; |
AW: liege ich richtig mit dem OOP-Versuch
Danke für die schnellen Hinweise. Die Veränderung Destroy habe ich vorgenommen. Muss ich wirklich immer in derartigen Programmen einen destructor aufrufen?
Mehrfach habe ich gesehen, dass darauf verzichtet wurde. Wann und unter welchen Voraussetzungen muss ich den Speicher wirklich wieder frei geben? Die Methoden, auf die die Propertys zugreifen (hier setLaenge, setBreite und GetFlaecheninhalt) lassen sich nicht in private oder protect verstecken. Wie sollte ich also diese Methoden besser verstecken können ähnlich wie die private-Felder und Methoden FLaenge, FBreite, FFlaecheninhalt; function GetLaenge; und function GetBreite? |
AW: liege ich richtig mit dem OOP-Versuch
Hallo Fritzew, in meinen Studien bin ich auf die Seite gestoßen:
![]() da wird u.a. zu Klassen und Objecte beispielhaft aufgeführt: "...Beispiel: Eine Klassenmethode „simuliert“ eine Klassenvariable und zählt, wie viele Objekte es von einer Klasse gibt:
Delphi-Quellcode:
Im Konstruktor (Create) wird die Anzahl erhöht, im Destruktor (Free) wieder herabgesetzt. Über die Klassenmethode Count (und natürlich über die globale Variable)
Unit Flaeche;
Interface Type TFlaeche = class(TObject) private protected Function BerechneFlaeche: Double; virtual; abstract; Function BerechneUmfang: Double; virtual; abstract; public Constructor Create; Destructor Free; Class function count: Integer; Property Flaeche: Double read BerechneFlaeche; Property Umfang: Double read BerechneUmfang; End; Implementation Var anzahl: Integer; Constructor TFlaeche.Create; Begin Inc(anzahl); End; Destructor TFlaeche.Free; Begin Dec(anzahl); End; Class Function TFlaeche.Count: Integer; Begin result := anzahl; End; End. kann nun festgestellt werden, wie viele Instanzen es von TFlaeche gibt......" Ich habe mich an diesem Beispiel orientiert, wohl falsch. Hier wird mit dem Destructor TFlaeche.Count.Free gearbeitet. Sollte man also immer "destructor ....Destroy" einsetzen? Warum "override " was überschreibe ich da? |
AW: liege ich richtig mit dem OOP-Versuch
Zitat:
Zitat:
Der Grund weshalb man davon nicht abweichen sollte deckt sich mit deiner nächsten Frage Zitat:
Delphi-Quellcode:
ab. TObject hat einen Destruktor mit dem Namen "Destroy". Wenn ein Objekt deiner Klasse zerstört werden soll müssen alle Destruktoren die ganze Vererbungshierarchie hinauf abgearbeitet werden bis man bei TObject ankommt.
TObject
Der Destruktor von TObject ist "virtuell". Das bedeutet dass Unterklassen (z.B. deine) das Verhalten von "Destroy" abändern können. In deinem Fall zählt es die Klassenvariable "Anzahl" eins herunter damit man sieht dass es in der Welt nun eine Fläche weniger gibt. Doch hiernach muss im Destruktor noch "inherited" aufgerufen werden damit der Destruktor von TObject aufgerufen wird. Das fehlt in deinem Tutorial ebenfalls, das ist falsch. Schau mal zu Themen wie "Vererbung" und "Polymorphie". Liest sich vielleicht beim ersten mal etwas wild, aber eigentlich ist es ganz einfach. Als absolute Kurzfassung, so wäre das Tutorial korrekt:
Delphi-Quellcode:
interface
type TFläche = class // Man kann auch "TFläche = class(TObject)" schreiben public destructor Destroy(); override; end; implementation destructor TFläche.Destroy(); begin // Tue etwas inherited; end; |
AW: liege ich richtig mit dem OOP-Versuch
Das Tutorial ist überarbeitungsbedürftig. Ich habe es auf meine ToDo-Liste gesetzt.
|
AW: liege ich richtig mit dem OOP-Versuch
Danke für die Hinweise zum Destructor. Werde ich mir nochmals in Ruhe ansehen.
Warum sich bestimmte Methoden nicht verbergen lassen liegt im konkreten Fall daran, dass im Formular diese Methoden aufgerufen werden und wenn sie nicht public sind, geht es nicht. Was könnte ich dagegen tun? Ich habe erkenntlich TForm in eine unit und TFlaecheninhalt in eine weitere unit gepackt. TForm-Methoden(Buttonclick...) greifen auf GetFlaecheninhalt beispielsweise zu :
Delphi-Quellcode:
Das ist mein kleines Problem. Oder muss ich damit leben?
procedure TForm1.BerechneFlClick(Sender: TObject);
begin Flaecheninh.setLaenge(strtoint(Laenge.text)); Flaecheninh.setBreite(strtoint(Breite.text)); LbFlaecheninhalt.Caption:=inttostr([B]Flaecheninh.GetFlaecheninhalt[/B]); end; |
AW: liege ich richtig mit dem OOP-Versuch
Greif nicht auf die Methoden sondern auf das Property zu. Dafür ist das ja da.
|
AW: liege ich richtig mit dem OOP-Versuch
So hätte ich es gemacht:
Delphi-Quellcode:
Wozu der Zähler? Wenn jemand mehrere Flächen berechnen will, dann soll er das selbst implementieren. ;)
Type
TRechteck = class(TObject) private FLaenge: double; FBreite: double; FFlaeche: double; FUmfang: double; procedure BerechneFlaeche: Double; procedure BerechneUmfang: Double; procedure SetLaenge(laenge: double); procedure SetBreite(breite: double); public Property Laenge: Double write SetLaenge; Property Breite: Double write SetBreite; Property Flaeche: Double read FFlaeche; Property Umfang: Double read FUmfang; End; procedure TRechteck.SetLaenge(laenge: double); begin // ToDo: // wenn kleiner 0 -> Exception auslösen "Länge darf nicht kleiner 0 sein" // oder besser allgemeine Exception InvalideArgument laenge := FLaenge; end; procedure TRechteck.SetBreite(breite: double); begin // ToDo: // wenn kleiner 0 -> Exception auslösen "Breite darf nicht kleiner 0 sein" // oder besser allgemeine Exception InvalideArgument breite := FBreite; end; procedure TRechteck.BerechneFlaeche; begin FFlaeche := FLaenge * FBreite; end; procedure REechteck.BerechneUmfang; begin FUmfang := (2 * FLaenge) + (2 * FBreite); end; /////////////////////////////////////////////////////////////////////////////// procedure TForm1.BerechneFlClick(Sender: TObject); var TRechteck: Rechteck; Flaeche: double; begin Rechteck := TRechteck.Create; try // Eingaben validieren, wenn valid dann: Rechteck.Laenge := ...; Recheck.Breite := ...; Flaeche := Rechteck.Flaeche; finally Recheckt.Free; end; end; Aber du scheint das Prinzip der Objektorientierung noch nicht so ganz verstanden zu haben:
Delphi-Quellcode:
Du willst anscheinen eine allgemeine Klasse schreiben, um Fläche und Umfang verschiedener geometrischer Körper zu berechnen. Und die Kind-Klassen sollen dann BerechneFlaeche und BerechneUmfang selbst implementieren. Idee gut. Aber Namensgebung schlecht. Die Klasse heißt TFlaeche. Warum berechnet eine Klasse TFlaeche den Umfang?
Type
TFlaeche = class(TObject) private protected Function BerechneFlaeche: Double; virtual; abstract; Function BerechneUmfang: Double; virtual; abstract; public
Delphi-Quellcode:
TGeometrischerKoerper = class(TObject)
Delphi-Quellcode:
TRechteck = class(TGeometrischerKoerper)
Delphi-Quellcode:
TDreieck = class(TGeometrischerKoerper)
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:52 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