Hey, jetzt zum Open Close Principle. Ich habe dafür
auch wieder ein kleines Beispiel gebaut und sehen wir uns einfach mal
die Klassen kurz an. Wir haben hier zum Beispiel Kreis,
kriegt einen Radius mit und kann ihn auch wieder zurückgeben.
Rechteck, so ähnlich, eine Breite und eine Höhe
wird dem Konstrukte übergeben und kann beides auch wieder zurückgeben.
Die Klasse Startup hat wie immer die Main-Methode.
Hier wird eine Railist erzeugt
Und da wird dann jeweils ein neues Exemplar der Klasse Kreis
übergeben, also eine Raillist mit Lement-Typ Kreis.
Wir haben hier eine Raillist mit Element-Hyprechteck und da werden einfach
auch zwei Neuexemplare der Klasse Rechteck übergeben.
Und dann haben wir hier einfach ein System Out Printline,
in dem wir auf der Klasse Gesamtflächenberechne,
die offensichtlich statische Methode berechne,
Gesamtfläche aufrufen und da die beiden Listen übergeben.
Jetzt gucken wir uns hier
den Gesamtflächenberechner mal an
Und er nimmt hier die beiden Listen entgegen,
hat initialisiert hier eine Variable vom Typ Double,
die Gesamtfläche heißt mit null,
zählt dann für jedes Element aus der Liste Kreis,
die hier berechnete Fläche zu der Gesamtfläche hinzu.
Und das Gleiche passiert hier mit Rechteck dann auch nochmal.
Ist natürlich irgendwie nicht ganz so schön, dass wir hier zwei Listen brauchen.
Also könnten wir uns ja eigentlich mal ein Interface bauen,
sodass wir eine Oberkategorie haben,
sodass wir hier als Elementtyp einen gemeinsamen statischen Typ reintun können.
Das machen wir also mal
Interface, das nennen wir mal bei Shape. Ich bin es eigentlich gewohnt,
Interface ist mit dem großen I beginnen zu lassen,
ganz im Gegensatz zu dem, was wir hier eigentlich bei SE2 machen,
weil es da so ist,
dass die Interfaces einfach gar keinen Prefix haben und dafür die implementierenden Klassen das Post-Fix-Impel,
ich glaube überall draußen macht man es eher so,
deswegen würde ich das jetzt auch mal so lassen.
In das Interface tue ich erstmal noch gar nichts rein,
ich weiß, leere Interfaces sind blöd,
aber da kommt ja später auch noch was rein,
aber wir wollen erstmal die beiden Listen loswerden,
beziehungsweise nur noch eine Liste haben müssen.
Also könnten wir hier eigentlich dann sagen, wir machen hier ein Elementtyp, I shape.
Hier natürlich dann auch. Dann wäre es natürlich blöd,
wenn das Ding Kreislist hieße, also würde ich das umbenennen wollen,
damit es jetzt nicht überall ändern muss, habe ich einen Shortcut,
das ist auf der Shortcut der Woche,
das ist Shift,
Alt,
R. Und das macht dann Refactor Rename
Ähm, und dann würde ich hier die Kreislist einfach in Shapelist umbenennen.
Das macht es dann hier auch überall. Ähm,
dass dieses Ad noch nicht funktioniert, es liegt schlicht und einfach daran,
dass wir kreisen und nicht haben,
dass Interface implementieren lassen,
also im... I shape.
Schon hört hier das Gemecker auf. Diese Rechtecklist brauchen wir ja nicht mehr,
weil wir jetzt alles in so eine gemeinsame Liste reintun wollen.
Und jetzt würde ich Rechtecklist auch umbenennen wollen.
Mal sehen, ob wir das mit mir auch macht.
Ja, das nennen wir dann auch Shapelist. So,
und wir haben das Rechteck ja auch noch nicht,
das Interface implementieren lassen
. Shape
So, mal ganz kurz speichern, dann gucken wir uns hier Start-up an.
Jetzt sagt er, berechne Gesamtfläche, klappt so nicht mehr.
Natürlich klappt das so nicht mehr, weil wir hier eigentlich
zwei Listen erwarten, mit Element-Typ, Kreis beziehungsweise Rechteck.
Also machen wir hier auch einen Shape draus.
Diese Kreislist machen wir wieder Shift,
halt R und benennen sie um in Shapelist
Und diese Liste brauchen wir dann gar nicht mehr.
Die nehmen wir hier einfach mal raus. So, und
jetzt würde ich hier als Elementtyp bei Shape haben müssen.
Und das hier können wir uns mit alt und den Feiltasten
nach oben holen. Das können wir wegnehmen,
weil es ist ja gerade der Vorteil,
dass wir nicht mehr zwei Listen haben,
dass wir auch nicht zwei erweiterte Vorschleifen haben.
Und hier Get Radios kennt er natürlich nicht, weil wir
immer das Ganze nur auf dem statischen Typ machen können.
Ich benenne das hier nochmal in Shape um. So und
das hier auch. Genau. Und jetzt will er hier
Get Breite und Get Höhe für das Rechteck nicht machen,
weil ja, wie gesagt, nur die Methoden,
die im statischen Typ, und der ist ja I shape,
drin ist, verwenden kann.
Und wir haben hier in unserem I shape noch überhaupt
gar keine Methoden drin. Also müssen wir, Entschuldigung,
hier müssten wir hier wieder so eine Fallunterscheidung machen,
solche Fallunterscheidungen mit Instance Offs sind immer blöd,
deswegen kommen die dann später auch wieder weg,
aber erstmal machen wir sie da rein,
damit der Code läuft,
if shape,
instance of
Kreis. Dann können wir uns die statische Valiable vom Typ Kreis machen.
Den nennen wir Kreis. Gleich und dem weisen wir Shape zu.
Und natürlich müssen wir hier die Typzusicherung machen, nämlich auf Kreis.
Und dann können wir uns das da reinholen und schon sieht man,
dass es blöd war,
dass ich diese Umbenennung Key of Shape gemacht habe,
weil ich ja eigentlich diese variable, die mich,
den statischen Typ preisgegeben habe, hier aufrufen will oder hier benutzen will.
Jetzt funktioniert das, das gleiche Spiel machen wir mit
dem Rechteck, if Shape, Instanz.
Auf Rechteck
Machen wir hier wieder unsere schweiften Klammern hin,
das ziehen wir uns mit Alt-Pfeiltasten nach oben,
machen wir vorher noch statisch Variable vom Typ,
eine Variable vom statischen Typ, Rechteck.
Gleich. Das machen wir wieder, Typ zur Sicherung,
gleich, weiß nicht, Shape zu.
Natürlich wäre es ganz gut, wenn so eine Variable auch
einen Namen hätte, Rechteck.
Und hier muss Rechteck rein für unsere Typ
zur Sicherung
So, noch ein bisschen Kohle und dahinter und dann
können wir hier auch rechteck machen.
Also es war einfach blöd von mir, dass ich das
Ganze in Shape umbenannt habe. Ich hätte wissen müssen,
dass ich an der Stelle eigentlich eine Variable vom statischen Typ
Rechteck haben möchte und die einfach Rechteck nenne.
Okay, jetzt müssen wir ins Startup nochmal gucken.
Hier haben wir ja zwei Listen,
das haben wir ja in Gesamtflächenberechner geändert, auf eine.
Also können wir hier
auch eine rausnehmen
So, und jetzt packen wir schlicht und einfach sämtliche Formen in
unsere Raillist vom Elementtyp I shape und können darauf jetzt einfach mal Flächenberechnung laufen lassen,
Run ist Java Application und hier unten sehen wir eine berechnete Fläche,
in was für Einheiten auch immer.
Ich tue einfach mal so, als wenn da stimmen würde,
das stimmt natürlich auch. Jetzt haben wir natürlich irgendwie so ein ganz klein bisschen das Problem,
dass wenn wir uns unseren Gesamtflächenberechner angucken,
wir hier wieder unsere ekligen Fallunterscheidungen haben, wenn Shape,
Instance of Kreis, berechnet die Fläche so,
wenn Shape Instance of Rechteck berechnet die Fläche so,
wenn wir jetzt ein Dreieck hinten, dann hätten wir wieder Elsive, Shape Instance of Dreieck.
Jetzt kann man sich nur eine ganze Menge mehr Formen ausdenken,
wofür wir dann immer eine andere Gesamtflächenberechnung bräuchten und natürlich auch immer,
also immer eine andere Art und Weise,
die Gesamtfläche zu erhöhen mit dieser Flächenberechnung hier und immer bräuchten wir wieder so eine Fallunterscheidung.
Das ist natürlich
irgendwie blöd
Also sorgen wir doch dafür, dass wir das ein bisschen allgemeiner machen können.
Jetzt gehen wir hier in die Klasse Kreis und bauen uns einfach mal eine Methode.
Die ist Public. Gibt ein Double zurück. Und einen
klein geschriebenen Double zurück. Und ihr ahnt schon, das
Ding wird berechnen. Fläche heißen sollen und genau das Ganze,
genau das auch tun sollen. Und das ist nichts anderes als,
wir haben hier ein Return und dann haben wir unseren Radius mal mass.p,
da haben wir es schon,
jetzt haben wir also hier in der Klasse Kreis,
eine Methode, die Fläche berechnet,
das können wir natürlich für das Rechteck auch machen.
Public Double.
Berechne. Fläche
Und dann wollen wir hier Return, naja, so ein
Rechteck ist breite mal Höhe. Und das Return dann eben
diesen Double. Und jetzt könnten wir das Ganze hier mal dahingehend umbauen,
einfach gar keine Fallunterscheidung mehr zu benutzen,
sondern hier tatsächlich jetzt Shape einzusetzen und dann auf dem jeweiligen Element in unserer Shapelist,
dessen Methode berechne Fläche aufzurufen, nämlich entweder etwas,
was im Kreis drinsteht oder das, was in Rechteck drinsteht.
Damit fangen wir einfach mal an. Das wird noch einen
kleinen Hick abgeben, aber den haben wir dann sofort gelöst.
So, jetzt können wir uns das sparen.
Wir können uns das sparen. Das hier rücken wir noch
ein bisschen vernünftig an
Und hier würden wir einfach sagen, Shape.
Die ganzen Punktmacher bietet er mir nicht berechnet Fläche an.
Deswegen schreibe ich es einfach mal von Hand.
Auf Klammer zu, warum wird es nicht angeboten?
Weil wir ja, wie bereits gesagt,
nur die Methoden aus dem statischen Typ benutzen können.
Der statische Typ ist ja I-Shape. Und da haben wir
berechnet vielleicht einfach nur noch gar nicht reingetan.
Wenn wir das jetzt machen, also Double, Böse,
echt eine Schläche. Klammer auf, Klammer zum Semikolan.
Und dann speichern, dann funktioniert das Ganze.
In Rechteck funktioniert irgendwas nicht. Warum schimpft er hier mit
uns Add-Un-Implemented Methods? Ja, ich habe Fläche falsch geschrieben.
So, und schon funktioniert das
Und jetzt können wir hier in unseren Gesamtflächenberechner alles nehmen,
was ein Shape ist und auf dem die jeweilige Methode, berechne Fläche aufrufen.
Und wenn wir das hier einfach mal machen mit Run Ass,
Java Application, dann entsteht hier die gleiche Gesamtfläche,
wie da vorher aufstand, mit deutlich kürzerem Code.
Und jetzt kommen wir auch zu dem eigentlichen Open-Close-Prinzip.
Open-Close-Prinzip, was sich am Anfang ein bisschen komisch anhört,
steht für offen für Erweiterungen und geschlossen für Veränderungen.
Sowas kommt gerne auch mal in Lückentexten in Klausuren vor.
Also offen für Erweiterungen und geschlossen für Veränderungen, was nichts anderes bedeutet,
als wir können uns noch so viele Formen ausdenken, wie wir wollen.
Wir müssen die jeweiligen Klassen einfach nur I shape implementieren lassen.
Das heißt, die brauchen eine Methode,
berechten Fläche, die ein Double zurückgibt,
dann können wir die alle, wie wir wollen,
hier in unsere Liste reintun und der Gesamtflächenberechner funktioniert vollkommen ohne Veränderung.
Das heißt also, wir sind offen für Erweiterungen zu anderen Shapes
in und wir sind abgeschlossen gegenüber Veränderungen.
Das heißt also, wir müssen eigentlich keine Zeile Code ändern,
wenn wir weitere Formen hinzufügen. Wir müssen nur die jeweilige Klasse bauen,
die muss I shape implementieren und dann funktioniert unsere Brechenmethode ganz genauso,
wie sie die ganze Zeit vorher auch schon funktioniert hat.
Das war jetzt also das Open Close Principle und das
war es von mir auch für diese Woche.
Und wir sehen uns dann nächste Woche.
Bis dann