OOP - Vererbungslehre
Dieses Tutorial ist die Fortsetzung von Step 19, in dem zu Beginn die Vererbung bereits am Beispiel der Klasse
TBitBtn kurz angedeutet wurde. Lass uns diesen Punkt nochmal genauer anschauen.
Was ist Vererbung?
Vererbung ist ein Phänomen, um spezialisiertere Objekte, verschiedener Art und Weise zusammenzufassen und
doch um bestimmte Funktionalitäten und/oder Eigenschaften zu erweitern.
Die Elternklasse beinhaltet alle Attribute (=Felder) und Methoden, welche dann auch in der vererbten Klasse
verfügbar sein können, sofern sie an der dafür vorgesehenen Stelle deklariert wurden.
Wenn wir wollen, dass etwas in der abgeleiteten Klasse verwendet, verändert oder sogar überschrieben werden
kann, so sollte dies mindestens unter protected deklariert werden. Alles unter private deklariert wurde ist
in den "Kinder"-Klassen nicht verfügbar. Auf die Felder unter private kann nachträglich nur noch durch
Einfügen von sogenannten Properties schreibend und lesend zugegriffen werden.
Properties werden bei der Vertiefung näher beleuchtet. Hier wollen wir erstmal in die die Vererbung einleiten.
Wer mit den Begriffen private/protected aber auch public und published noch nichts anfangen kann, sollte den
Theorie-Teil aus
Step 19
sich vorher anschauen oder im verlinkten SocialMedia ihre oder seine Fragen stellen.
Und was hat es mit dieser Vigenére-Verschlüsselung auf sich?
Die Vigenére-Verschlüsselung ist kurz gesagt eine Erweiterung der Caesar-Verschlüsselung. Hierbei können wir
mit einem Passwort die "Verschiebung" definieren. Für die weitere Theorie, was dahinter ist, darf gerne wieder
die Internet-Recherche genutzt werden. Hier gibt es viele Seiten, die auf die Theorie dahinter weiter eingeht.
Für uns reicht erstmal die Info, dass wir wieder Buchstaben austauschen, wie es bei Caesar der Fall war.
Um hier gleich durchstarten zu können, nutzen wir die "Copy-Paste" und kopieren einfach erstmal den ganzen
Projekt-Ordner und öffnen von dort aus das Projekt. Anschließend können wir es direkt durch
"Projekt speichern unter" unter einem neuen Namen abspeichern: "OOP2Beispiel".
Was wollen wir nun mit Vererbung machen?
Wie in Step 19 erstellen wir nun eine neue Unit mit dem Namen "mVigenere.pas". In dieser Unit deklarieren wir
auch vergleichbar mit Step 19 den type TVigenere, mit der Ausnahme, dass wir nicht von TObject ableiten,
sondern von TCaesar. Um dies machen zu können müssen wir erstmal in die uses die unit mCaesar einbinden.
Das ganze sollte dann etwa so aussehen:
unit mVigenere; interface uses mCaesar; type TVigenere = class(TCaesar) private { private declarations } protected { protected declarations } public { public declarations } published { published declarations } end; implementation end. |
Den Constructor deklarieren wir genau wie in Step 19, nur mit dem Unterschied, dass dieser nun einen Parameter
"password:String" bekommt:
constructor Create(password:String); |
Nun müssen wir erst noch das Feld fPassword:String im privat-Abschnitt deklarieren.
Hiernach können wir es im Constructor initialisieren:
constructor TVigenere.Create(password:String); begin inherited Create; fPassword:=password; end; |
Wie im Constructor kann mittels "inherited" die function DeCode des Elternobjektes TCaesar aufgerufen werden.
Somit ist es möglich den Algorithmus der Caesar-Verschlüsselung auszuführen.
Wir deklarieren zunächst drei Integer-Variablen:
IndexSource: Index des zu codierenden Strings durchgehen.
IndexPw: Index des Passwortes.
code: Verschiebung von A -> move.
Und zu guter letzt noch einen String:
coded: Codiertes Wort.
IndexSource: Index des zu codierenden Strings durchgehen.
IndexPw: Index des Passwortes.
code: Verschiebung von A -> move.
Und zu guter letzt noch einen String:
coded: Codiertes Wort.
Das folgende Schaubild soll den Algorithmus der Vigenére-Verschlüsselung veranschaulichen:
Und hier der kommentierte Script dazu:
var indexOrig, // Index des Original-Strings indexPw, // Index des Passwort-Strings move : Integer; // Verschiebung coded : String; // Codierter String begin // Variablen initialisieren: indexOrig:=0; indexPw:=0; coded:=''; while indexOrig < Length(orig) do // Während noch Buchstaben zu bearbeiten sind begin Inc(indexOrig); // nächsten Buchstaben behandeln Inc(indexPw); // Passwortindex um eins erhöhen // Wenn Passwortindex größer als Länge des Passwortes if indexPw > Length(fPassword) then // Passwortindex auf 1 zurücksetzen indexPw := 1; // Buchstabe des Passwortes in ASCII-Zahl codieren und ord('a') abziehen // hierbei resuliert für z.B. fPassword[indexPW]='a' move = 0; move := ord(fPassword[indexPw])-97; if decode then // wenn decodiert werden soll move := 26-move; // dann move umdrehen -> Rückwärts verschieben // Funktion der Klasse TCaesar mit aktulellem Buchstaben bei indexOrig ausführen coded := coded + inherited DeCode(orig[indexOrig],move); end; // codierten String zurückgeben result:=coded; end; |
Nun haben wir die mVigenere.pas fertiggestellt. Um diese nun nutzen zu können, brauchen wir einige
Änderungen in der MainUnit und dem Formular. Der folgende Screenshot zeigt, wie das Edit EdPassword für die
Passwort-Eingabe und die RadioButtons rbCodieren bzw. rbDecodieren zur Unterscheidung von Codierung und
Decodierung eingesetzt. Andere Elemente, die wir nicht benötigen, wurden entfernt.
Im ButtonClick-Event wird jetzt nur noch das EVA-Prinzip angewand.
Die Eingabe wird durch eine Instanz von TVigenere durch Aufruf von DeCode und rbCodieren.Checked als
zweiten Parameter direkt in edAusgabe codert oder decodiert wiedergegeben. Der folgende Source-Ausschnitt
zeigt diese Implementierung.
edAusgabe.Text := vigenere.DeCode( edEingabe.Text, rbCodieren.Checked); |
Der vollständige Sourcecode befindet sich auch hierfür auf
GitHub. Viel Spaß damit :)
Wer nun alle Steps durchgearbeitet hat, kann nun gerne die Aufgaben im nächsten Step bearbeiten ;-)