![]() |
Allgemeines zu Klassen / Objekten
Nehmen wir mal folgende Klassen oder sind es Objekte als Diskussionsgrundlage:
Klasse / Objekt 1:
Delphi-Quellcode:
Variante 2:
type TFooClass = class
private FFooCaption : String; procedure SetFooCaption; funktion GetFooCaption: String; procedure FooCaptionPlusSr; public constructor create; end; procedure TFooClass.create; begin SetFooCaption; end; procedure TFooClass.SetFooCaption; begin FFooCaption := 'Hello'; end; function TFooCaption.GetFooCaption: String; begin result := FFooCaption; end; procedure TFooClass.FooCaptionPlusStr; begin FFoocaption := FFooCaption+', world'; end;
Delphi-Quellcode:
So, der Unterschied sollte klar sein. Mit Variante eins kann ich über Methoden auf die Membervariable FFooCaption zugreifen. Aber man kann ja auch so drauf zugreifen:
type TFooClass = Class
private FFooCaption: String; procedure FooCaptionPlusSr; public constructor create; end; constructor TFooClass.Create; begin FFooCaption := 'Hello'; end; procedure TFooClass.FooCaptionPlusStr; begin FFoocaption := FFooCaption+', world'; end;
Delphi-Quellcode:
Jetzt stellt sich mir die Frage wie macht man es richtig oder sollte man es machen? Immer über Methoden auf die Membervariablen zu greifen oder geht es auch direkt, wie in Beispiel 2? Bitte mit Begründung antworten, sonst nützt es mir nicht viel.
var
FooClass: TFooClass; s : String; begin FooClass := TFooClass.Create; ...; ...; s := FooClass.FFooCaption; Noch was. Wann müssen / sollen Methoden, Membervariablen unter public deklariert werden? |
Die Antworten, welche Du jetzt erwartest basieren wohl größtenteils auf "Glauben". Kurz, jeder wie es ihm gefällt.
Deshalb einfach mal, wie ich es mache und mit der Lösung fahre ich recht gut und wohl auch entlang (oder mitten im) Mainstream.
Delphi-Quellcode:
Im Create setze ich i.A. die Variable (ioB: FFooCaption) direkt, sofern der Wert konstant ist bzw. nicht validiert werden muss. Wird mit dem Setzen gleichzeitig eine Validierung durchgeführt, gehe ich über die Property und damit ultimativ auch über die write Methode. Allerdings versuche ich im Create eine solche Situation zu vermeiden und zwinge den Programmiere die Werte anschließend separat zu setzen, damit werden auch hier entstehende Fehlerquellen offensichtlicher.
type TFooClass = class
private FFooCaption : string; procedure SetFooCaption(const Value: string); function GetFooCaptionEx: string; public constructor create; property FooCaption: string read FFooCaption write SetFooCaption; // kleiner fehler korriegert (Ex am Ende vergessen) property FooCaptionEx: string read GetFooCaptionEx; end; Zitat:
...:cat:... |
Jetzt hast du noch eine Möglichkeit eingebracht mit property. :? Was ist denn der Vorteil, wenn man über property geht und es nicht so macht wie ich im ersten Beispiel?
Also wenn der Wert überprüft werden muß, würdest du über eine Methode gehen? Klingt sinnvoll anderst ist es ja auch nicht möglich, es sei denn man sagt der Programmierer ist selber dafür verantwortlich. Aber das wäre ja blöd dann muß er ja, wenn er mit dem Objekt arbeitet immer selber eine Überprüfung machen. ist also sinnvoll dies von der Klasse erledigen zu lassen. OK, das habe ich verstanden. Aber um noch mal auf private und public zu sprechen zu kommen: Warum steht das
Delphi-Quellcode:
nicht im private-Abschnitt bei dir?
property FooCaption: string read FFooCaption write SetFooCaption;
property FooCaptionEx: string read GetFooCaption; Nachtrag: Ich kann doch auch den Wert von FooCaption bekommen (bei dir) mit:
Delphi-Quellcode:
s := FooCaption.GetFooCaptionEx;
|
Erst mal schnell: im obigen Beitrag habe ich im Code noch einen kleinen Fehler korrigiert ;)
Delphi-Quellcode:
So würde das erst einmal bei mir aussehen. In Create greife ich direkt auf die Variable FFooCaption zu, da der Wert eh konstant ist und somit keiner Überrpüfung bedarf. Wenn ich die Regeln ändere muss ich allerdings manuell überprüfen, ob der konstante Startwert immer noch den Bedingungen entspricht ;)
type TFooClass = class
private FFooCaption : string; procedure SetFooCaption(const Value: string); function GetFooCaptionEx: string; public constructor Create; property FooCaption: string read FFooCaption write SetFooCaption; // kleiner fehler korriegert (Ex am Ende vergessen) property FooCaptionEx: string read GetFooCaptionEx; end; constructor TFooClass.Create; begin inherited; FFooCaption := 'Default'; end; procedure TFooClass.SetFooCaption(const Value: string); begin if FFooCaption <> Value then begin // überprüfen, ob der wert "ok" ist if Trim(Value) = '' then raise Excpetion.Create('FooCaption muss einen nicht-leeren String enthalten'); FFooCaption := Trim(Value); end; end; function TFooClass.GetFooCaptionEx: string; begin Result := Format('Die FooCatpion ist "%s".', [FooCaption]); end; Wenn die Eigenschaft FooCaption gesetzt wird, dann überprüft die Funktion jetzt, ob der neue Wert auch alle Regeln entspricht. Hier könnte auch noch andere Routinen (z.B. Neu Zeichen :: TControl.Invalidate) und Ereignishandler (TOnEmptyValue) vorkommen. In der Funktion GetFooCaptionEx greife ich dann auf FooCaption und nicht auf FFooCaption zurück. In der aktuellen Lösung ist das zwar genau das Gleiche, falls sich die Implementation jedoch mal ändern sollte, so das vor der Rückgabe von FooCaption noch eine Methode ausgeführt wird, dann stimmt es auch nach der Änderung der Implementation sofort. Property vs. Funktionen Da gibt es nicht viel zu sagen, ausser dass es wahrscheinlich schneller zu tippen geht, wenn ich immer nur Object.FooCaption für setzen/auslesen schreiben muss, anstatt von Object.GetFooCaption für das Lesen und Object.SetFooCaption(...) für das Schreiben. Es ist einfach "schöner". Ausserdem macht es anderen Entwicklern den Umgang mit Deinen Objekten leichter. Noch kurz zu der Frage, wie Du die FooCaptionEx erhälst:
Delphi-Quellcode:
Folgender Code:
var
FooClass: TFooClass; begin FooClass := TFooClass.Create; try Self.Caption := FooClass.FooCaptionEx; // Self ist z.B. TForm1 finally FooClass.Free; end;
Delphi-Quellcode:
steht im public Bereich, damit vorhergendes Konstrukt auch dann funktioniert, wenn TFooClass und TForm1 in verschiedenen Units deklariert sind.
property FooCaption: string read FFooCaption write SetFooCaption;
property FooCaptionEx: string read GetFooCaption; ...:cat:... |
Zitat:
Zitat:
Danke für deine Erklärungen. Mal sehen, wie ich das in Zukuft umsetzen kann. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:49 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