1. Eckstein, Echstein, alles muss versteckt sein ;)
...oder: Das Geheimnisprinzip
Im Kurs Anfängerwissen haben wir angeschnitten, wo man Variablen deklarieren kann.
Was wir hier nicht so genau dabei betrachtet haben ist, was die Gründe dafür sind.
Wieso soll man es so machen und nicht anders?
Zum Beispiel kann man ja ein Array einfach global deklarieren. Also direkt in var im Interface-Abschnitt, direkt
unter der Zeile, in der Form1 deklariert ist.
Aber was bringt es uns, wenn wir in einer anderen Unit auch ein Array mit dem gleichen Namen, aber für einen
anderen Zweck nutzen wollen?
Und hier kommt die wichtigste Regel ins Spiel, wenn es um die Deklaration von Variablen/Feldern/Zugriffsgedöns
geht:
Beachte zudem:
- alle Variablen sollten möglichst aussagekräftig bezeichnet werden. (Lesbarkeit)
- hat man nur globale Variablen, schafft dies Unübersichtlichkeit - wo wird was wann benutzt? (Wartbarkeit)
- globale Variablen oder Objekte können von überall benutzt werden. In der OOP benutzt man hierfür jedoch s.g. "Properties" in den Objekten. Damit kann eine Eigenschafft eines Objekts als "Globale Variable" benutzt werden, wenn auf das Objekt zugegriffen wird. Näheres folgt noch.
- globale Variablen verbrauchen immer den Speicher, den sie verbrauchen; lokale nur dann, wenn sie direkt gebraucht werden. (Speichereffizienz, sollte auch heutzutage bedacht werden!)
Beispiel für Deklaration und Verwendung von Properties:
type TAuto = class(TForm) private fColor : TColor; fHeight : Integer; fWidth : Integer; fMaxWeight : Integer; public property Color : TColor read fColor write fColor; property Height : Integer read fHeight write fHeight; property Width : Integer read fWidth write fWidth; property WeightLoadMaximum : Integer read fMaxWeight; constructor Create( AColor:TColor; AHeight, AWidth, AMaxWeight: Integer); end; |
Das Schlüsselwort "write"/"read" sorgt dafür, dass wir auf die Eigenschafft schreibend/lesend
zugreifen können.
Ist MyCar eine erstellte Instanz unseres Objektes...
// so wäre das möglich: MyCar.Color := clBlue; MyCar.Height := 1.3; MyCar.Width := 1.6; MyCar.Length := 2.4; // das jedoch nicht: MyCar.WeightMaximum := 10000; |
Grund hierfür ist einfach, dass wir keine Schreibberechtigung für die Eigenschafft WeightMaximum erstellt haben.
Ok, eigentlich geht es hierbei nicht darum es einfach zu "verstecken", aber wir können hier durch
die Verminderung der Zugriffsmöglichkeit auch noch Logik kapseln. Was ist, wenn bei jedem schreibenden Zugriff
ein bestimmter Sensor-Wert im Auto geprüft sein muss? Z.B. beim selbstfahrenden Auto wollen wir, dass es nur
Gas gibt, wenn der Sensor für den Frontabstand genügend "Luft" für noch mehr Geschwindigkeit hat.
Das ganze wäre zwar bestimmt ein Tick komplizierter im Detail, lässt sich aber durchaus auf so "kleine"
Logik-Bausteine herunterbrechen.
2. Methoden - Sichtbarkeit und Zugreifbarkeit "kompakt"
Wie wir es aus dem Anfängerbereich bereits kennengelernt haben, gibt es verschiedene Möglichkeiten beim
deklarieren von Parametern. Zur kurzen Wiederholung und Vertiefung einmal folgende Methode als Beispiel:
procedure initGame( APlayerName: String; var ALevel: Integer; const AGameType: Integer; APlayerList: TStrings); |
Beschreibung der Parameter:
Parameter | Beschreibung |
---|---|
APlayerName: String; |
Dies ist eine ganz normale Definition eines Parameters;
Hierbei werden die Werte der Variable übergeben.
d.h. wenn in der Methode initGame die Variable APlayerName verändert wurde
so ist die ursprüngliche Variable dennoch unverändert. => Call by Value |
var ALevel: Integer |
Hierbei wird auf jeden Fall eine Variable verlangt,
da hierbei nur der Zeiger auf die Adresse,
in der sich der Wert befindet, übertragen wird. => Call by Reference |
const AGameType: Integer; |
Hierbei kann alles mögliche übergeben werden.
Der Clue bei der Geschichte ist, dass weder der Wert
noch die Referenz verändert werden kann. => geschützter Parameter |
APlayerList: TStrings | Bei Parametern, die nicht grundsätzliche Datentypen sondern eigene Klassen sind, wird stets die Referenz, also "der Zeiger" übertragen. |
Somit dürfte der OOP-Bereich zum Thema der Sichtbarkeit erstmals erledigt sein :)