In diesem Artikel will ich eine Möglichkeit aufzeigen, wie so eine Klasse bemerkt, daß sich etwas geändert hat.
Man könnte der Klasse ein boolean Feld fModified spendieren, daß immer dann auf true gesetzt wird, wenn eines der Felder geändert wurde.
Das hat aber zwei Nachteile:
Erstens muß man immer dann, wenn man den Inhalt eines Feldes ändert daran denken, daß auch fModified auf true gesetzt werden muß.
Zweitens hat man immer wieder bei jedem schreibendem Zugriff die zusätzliche Tipparbeit.
Weiterhin erfolgt nicht automatisch eine Prüfung auf die Gültigkeit der Daten.
Abhilfe können hier die Properties schaffen.
Für den Anwender funktionieren die Properties genauso wie die Felder einer Klasse.
Der Clou ist aber, daß der Zugriff über Methoden erfolgen kann.
Code: Alles auswählen
type
TGeo = class
fModified : boolean;
fBezeichnung : string;
procedure SetBezeichnung(const Value : string);
property Bezeichnung : string read fBezeichnung write SetBezeichnung;
// hier folgen die weiteren Felder
end;
implementation
procedure TGeo.SetBezeichnung(const Value : string);
begin
if (fBezeichnung <> Value) then
begin
fBezeichnung := Value;
fModified := true;
end;
end;
Der Unterschied ist aber, dass der Wert nicht ohne Prüfung einfach in das Feld geschrieben wird,
sondern über die Zugriffsmethode SetBezeichung.
Diese prüft, ob sich der neue Inhalt überhaupt von dem bisherigen unterscheidet und nur falls dies der Fall ist, wird der neue Wert übernommen und gleichzeitig das Feld fModified auf true gesetzt.
Im obigen Beispiel wurde lesend einfach der Inhalt des Feldes fBezeichnung genommen. Aber auch hier kann man eine sogenannte GetterMethode verwenden.
Ein sinnvolles Beispiel dafür ist unsere Klasse TKreis.
Diese verwaltet ein zusätzliches Feld fRadius. Wenn der Anwender aber lieber den Durchmesser verwenden will, so kann das ganz einfach über eine Property mit Getter- und Settermethode erfolgen.
Code: Alles auswählen
type
TKreis = class ( TGeo )
fRadius : integer;
function GetDurchmesser : integer;
procedure SetDurchmesser(const Value : integer);
property Durchmesser : integer read GetDurchmesser write SetDurchmesser;
end;
implementation
function TKreis.GetDurchmesser : integer;
begin
Result := fRadius * 2;
end;
procedure TKreis.SetDurchmesser(const Value : integer);
begin
if (Durchmesser <> Value) then
begin
fRadius := Value div 2;
fModified := True;
end;
end;
Achtung. In dieser Methode ist eine Stolperfalle. Ich vergleiche den bisherigen Durchmesser mit dem neu übergebenen Wert.
Dieser Vergleich ruft impliziet die Methode GetDurchmesser auf. Lesend ist das OK. Man darf aber in der Settermethode keinesfalls schreibend auf die Property zugreifen.
Das würde eine Endlosschleife provozieren.
Wenn wir diese SetterMethode für alle Felder unserer Klassen definieren, brauchen wir uns um die Änderung nicht kümmern.
Allerdings nur wenn der Anwender der Klasse die Werte ausschliesslich über die Properties angepasst hat.