Schritt für Schritt zur klassenbasierten Programmierung - Teil 5

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1639
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Schritt für Schritt zur klassenbasierten Programmierung - Teil 5

Beitrag von fliegermichl »

In Teil 4 hatten wir 4 von TGeo abgeleitete Klassen definiert, welche konkrete geometrische Objekte darstellen.
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;
Auf die property Bezeichnung kann man ganz genauso zugreifen wie auf das Feld fBezeichnung.
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;
Obwohl TKreis gar kein Feld für den Durchmesser hat, kann dieser ganz einfach mit z.B. Kreis.Durchmesser := 50 gesetzt werden und wird durch SetDurchmesser automatisch in den richtigen Radius umgerechnet.

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.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6770
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Schritt für Schritt zur klassenbasierten Programmierung - Teil 5

Beitrag von af0815 »

Könnte das ganze in einen Thread zusammengefasst werden, anstatt für jedes Kapitel einen Thread zu machen ? Auch würde das ganze in der Wiki einen Sinn machen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

wp_xyz
Beiträge: 5142
Registriert: Fr 8. Apr 2011, 09:01

Re: Schritt für Schritt zur klassenbasierten Programmierung - Teil 5

Beitrag von wp_xyz »

af0815 hat geschrieben: Mi 26. Okt 2022, 17:11 Auch würde das ganze in der Wiki einen Sinn machen.
Absolut. Vergraben unter Tausenden anderer Nachrichten sind diese guten Beiträge bald verloren und die Mühe war umsonst...
Zuletzt geändert von wp_xyz am Mi 26. Okt 2022, 20:04, insgesamt 1-mal geändert.

hum4n0id3
Beiträge: 319
Registriert: So 5. Mai 2019, 15:23

Re: Schritt für Schritt zur klassenbasierten Programmierung - Teil 5

Beitrag von hum4n0id3 »

Soll hier OOP vermittelt werden, oder eben Klassenbasierte Programmierung. Und was ist dann Klassenbasierte Programmierung? Einzelne Klassen zu erstellen, oder Klassen als Container für Funktionen zu halten, scheint mir überdimensioniert zu sein und nicht vereinfacht. Klassen sind ja nicht als Container gedacht gewesen.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1639
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Schritt für Schritt zur klassenbasierten Programmierung - Teil 5

Beitrag von fliegermichl »

af0815 hat geschrieben: Mi 26. Okt 2022, 17:11 Könnte das ganze in einen Thread zusammengefasst werden, anstatt für jedes Kapitel einen Thread zu machen ? Auch würde das ganze in der Wiki einen Sinn machen.
Das hatte mir Mathias auch schon geschrieben. Ich hatte halt gedacht, falls zu den einzelnen Abschnitten Fragen oder Einwände auftauchen, kann man es hier im Forum besser diskutieren. Kann die Beiträge nicht am Ende einfach in das Wiki kopieren / verschieben?

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1639
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Schritt für Schritt zur klassenbasierten Programmierung - Teil 5

Beitrag von fliegermichl »

hum4n0id3 hat geschrieben: Mi 26. Okt 2022, 19:58 Soll hier OOP vermittelt werden, oder eben Klassenbasierte Programmierung. Und was ist dann Klassenbasierte Programmierung? Einzelne Klassen zu erstellen, oder Klassen als Container für Funktionen zu halten, scheint mir überdimensioniert zu sein und nicht vereinfacht. Klassen sind ja nicht als Container gedacht gewesen.
Klassenbasierte Programmierung ist ja OOP. Wobei es neben den Klassen ja auch noch statische TObject Konstrukte gibt.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6770
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Schritt für Schritt zur klassenbasierten Programmierung - Teil 5

Beitrag von af0815 »

fliegermichl hat geschrieben: Do 27. Okt 2022, 10:12 Kann die Beiträge nicht am Ende einfach in das Wiki kopieren / verschieben?
Nein, weil die Wiki eine eigene Formatierung braucht. Abr man kann dann in der Wiki einen Link hierher setzen, damit man weis wo man diskutiert.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Antworten