wiederholung:vererbung
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
wiederholung:vererbung [2022/11/28 07:28] – angelegt Martin Pabst | wiederholung:vererbung [2022/12/10 19:01] (aktuell) – [Beispiel 4: Feuerwerk] Martin Pabst | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
====== Vererbung ====== | ====== Vererbung ====== | ||
+ | Wir haben Klassen bisher als Mittel zur Schaffung übersichtlichen Codes kennengelernt: | ||
+ | ====== Beispiel 1: Erweiterung der Buntstift-Klasse ====== | ||
+ | Erinnert Ihr Euch an die Buntstift-Klasse aus dem [[wiederholung: | ||
+ | |||
+ | {{ youtube> | ||
+ | \\ \\ | ||
+ | |||
+ | <WRAP center round info 60%> | ||
+ | Warum stellen wir die erschwerende Forderung an uns, die Klasse '' | ||
+ | - Oft haben wir den Quelltext für existierende Klassen nicht, da sie Bestandteil großer kommerzieller Bibliotheken sind oder zur API der Programmiersprache gehören und vielleicht in einer anderen (maschinnennaheren und damit schnelleren) Programmiersprache implementiert sind. | ||
+ | - Selbst wenn wir den Quelltext einer Bibliothek haben, möchten wir in ihn nicht eingreifen, da wir sonst im Falle eines Updates der Bibliothek deren neuen Quelltext wieder von Neuem verändern müssten. | ||
+ | - Stellt Euch vor, wir wollen zusätzlich zur Klasse '' | ||
+ | </ | ||
+ | |||
+ | In einem ersten Schritt erstellen wir die Klasse '' | ||
+ | <code learnj> | ||
+ | class StiftNeu extends Buntstift { | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | < | ||
+ | |||
+ | <div class=" | ||
+ | |||
+ | <script type=" | ||
+ | StiftNeu stift = new StiftNeu(Color.red); | ||
+ | stift.schreibe(" | ||
+ | |||
+ | class StiftNeu extends Buntstift { | ||
+ | |||
+ | } | ||
+ | |||
+ | class Buntstift { | ||
+ | |||
+ | Color farbe; | ||
+ | |||
+ | | ||
+ | farbe = farbe1; | ||
+ | } | ||
+ | |||
+ | | ||
+ | println(text, | ||
+ | } | ||
+ | |||
+ | }</ | ||
+ | |||
+ | </ | ||
+ | |||
+ | </ | ||
+ | * Führe das Programm Schrittweise mit "step into ({{: | ||
+ | * Lass die Maus auf den Bezeichner '' | ||
+ | |||
+ | <WRAP center round info 60%> | ||
+ | Mithilfe des Schlüsselwortes '' | ||
+ | <code learnj [enable_line_numbers=" | ||
+ | class StiftNeu extends Buntstift { | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | dafür, dass die Klasse '' | ||
+ | Die neue Klasse, die von der bestehenden Klasse erbt, nennt man **Unterklasse**, | ||
+ | </ | ||
+ | |||
+ | Wir haben bisher also eine " | ||
+ | |||
+ | < | ||
+ | <div class=" | ||
+ | <script type=" | ||
+ | StiftNeu stiftGroß = new StiftNeu(Color.red, | ||
+ | stiftGroß.schreibe(" | ||
+ | |||
+ | StiftNeu stiftKlein = new StiftNeu(Color.lime, | ||
+ | stiftKlein.schreibe(" | ||
+ | |||
+ | class StiftNeu extends Buntstift { | ||
+ | |||
+ | | ||
+ | |||
+ | | ||
+ | super(farbe); | ||
+ | this.großschreibung = großschreibung; | ||
+ | } | ||
+ | |||
+ | | ||
+ | if(großschreibung) { | ||
+ | text = text.toUpperCase(); | ||
+ | } | ||
+ | super.schreibe(text); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | <script type=" | ||
+ | class Buntstift { | ||
+ | |||
+ | Color farbe; | ||
+ | |||
+ | | ||
+ | farbe = farbe1; | ||
+ | } | ||
+ | |||
+ | | ||
+ | println(text, | ||
+ | } | ||
+ | |||
+ | }</ | ||
+ | |||
+ | </ | ||
+ | |||
+ | </ | ||
+ | Da hab' ich Euch jetzt viel Neues zugemutet. Wir gehen alles schrittweise durch: | ||
+ | |||
+ | ==== Aufruf des Konstruktors der Oberklasse ==== | ||
+ | Schauen wir uns den Konstruktor der Klasse '' | ||
+ | <code learnj [enable_line_numbers=" | ||
+ | | ||
+ | super(farbe); | ||
+ | this.großschreibung = großschreibung; | ||
+ | } | ||
+ | </ | ||
+ | Da '' | ||
+ | <WRAP center round info 60%> | ||
+ | In Java **muss** jeder Konstruktor einer Unterklasse als **erste** Anweisung den Aufruf eines Konstruktors der Oberklasse enthalten. Dies wird mithilfe des Schlüsselwortes '' | ||
+ | </ | ||
+ | |||
+ | ==== Überschreiben von Methoden ==== | ||
+ | {{ : | ||
+ | Die Methode '' | ||
+ | |||
+ | <code learnj [enable_line_numbers=" | ||
+ | | ||
+ | if(großschreibung) { | ||
+ | text = text.toUpperCase(); | ||
+ | } | ||
+ | super.schreibe(text); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * Führe das Programm oben wieder schrittweise mit "step into ({{: | ||
+ | |||
+ | ==== UML-Diagramm ==== | ||
+ | Rechts siehst Du das UML-Diagramm der Klassen. Die Vererbung wird durch eine Linie von '' | ||
+ | **Erinnerung: | ||
+ | |||
+ | ====== Fachbegriffe ====== | ||
+ | {{ youtube> | ||
+ | |||
+ | ====== Beispiel 2: Fliegende Rechtecke ====== | ||
+ | {{ youtube> | ||
+ | Starte das Programm und regle die Geschwindigkeit langsam hoch! | ||
+ | < | ||
+ | |||
+ | <div class=" | ||
+ | |||
+ | <script type=" | ||
+ | new World(800, 800); | ||
+ | SystemTools.setSpeed(200); | ||
+ | |||
+ | while(true) { | ||
+ | new FlyingRectangle(); | ||
+ | } | ||
+ | |||
+ | |||
+ | class FlyingRectangle extends Rectangle { | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | super(360, 760 - 40, 80, 80); | ||
+ | setFillColor(Color.randomColor(50)); | ||
+ | setAlpha(Random.randdouble(0.2, | ||
+ | |||
+ | vx = Random.randdouble(-5, | ||
+ | vy = Random.randdouble(-26, | ||
+ | |||
+ | } | ||
+ | |||
+ | | ||
+ | move(vx, vy); | ||
+ | vy = vy + 0.2; | ||
+ | if(getCenterY() > 900) { | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | }</ | ||
+ | |||
+ | </ | ||
+ | |||
+ | </ | ||
+ | |||
+ | Damit die Seite nicht zu lange wird, findest Du die [[.flyingRectangle: | ||
+ | |||
+ | === UML-Diagramm zu " | ||
+ | {{ : | ||
+ | Auf dem nebenstehenden Diagramm habe ich die (sehr zahlreichen!) Attribute und Methoden der Klassen '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | < | ||
+ | <div style=" | ||
+ | </ | ||
+ | |||
+ | |||
+ | ====== Beispiel 3: Klasse " | ||
+ | Die Programmiersprache stellt bisher nur Objekte zum Zeichnen von Rechtecken, Kreisen, Polygonen und Sprites zur Verfügung. Ich zeige Dir, wie man durch Erweiterung der Klasse Polygon leicht weitere Objektklassen erstellen kann. Im Folgenden entwickeln wir eine Klasse " | ||
+ | |||
+ | ==== Skizze: ==== | ||
+ | {{ : | ||
+ | < | ||
+ | |||
+ | <div class=" | ||
+ | |||
+ | <script type=" | ||
+ | new Raute(400, 300, 50, 100); | ||
+ | new Raute(200, 200, 100, 80); | ||
+ | |||
+ | class Raute extends Polygon { | ||
+ | |||
+ | | ||
+ | double diagonaleX, double diagonaleY) { | ||
+ | | ||
+ | super(true); | ||
+ | |||
+ | addPoint(mitteX + diagonaleX/ | ||
+ | addPoint(mitteX, | ||
+ | addPoint(mitteX - diagonaleX/ | ||
+ | addPoint(mitteX, | ||
+ | |||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ====== Beispiel 4: Klasse " | ||
+ | Die Programmiersprache stellt bisher nur Objekte zum Zeichnen von Rechtecken, Kreisen, Polygonen und Sprites zur Verfügung. Ich zeige Dir, wie man durch Erweiterung der Klasse Polygon leicht weitere Objektklassen erstellen kann. Im Folgenden entwickeln wir eine Klasse " | ||
+ | |||
+ | ==== Mathematische Grundlagen ==== | ||
+ | {{ : | ||
+ | |||
+ | Wir wollen einen Stern mit $n$ Außenzacken zeichnen. Dazu brauchen wir die Koordinaten $(mitte_{x}, | ||
+ | Im Beispiel oben hat der Stern 5 Außenzacken (d.h. $n = 5$). Denke Dir eine Halbgerade, die im Mittelpunkt des Sterns beginnt und nach rechts zeigt. Sie geht durch den ersten Außenzacken des Sterns. Drehen wir sie um den Mittelpunkt des Sterns nach links, so überstreicht sie nach $360°/10 = 36°$ den ersten Innenzacken, | ||
+ | Der i-te Zacken erscheint also beim Winkel $i*36°$. Zur Berechnung seiner Koordinaten sieh' Dir oben das rechtwinklige Dreieck mit der roten und grünen Kathete an. Um die Koordinaten des zweiten Zackens zu berechnen muss die grüne Kathete zur x-Koordinate des Mittelpunkts addiert werden, die rote Kathete zur y-Koordinate: | ||
+ | $$ x = mitte_{x} + cos(i*36°)*radius $$ | ||
+ | $$ y = mitte_{y} + sin(i*36°)*radius $$ | ||
+ | Im Fall einer Außenzacke (gerades i, also '' | ||
+ | | ||
+ | |||
+ | < | ||
+ | |||
+ | <div class=" | ||
+ | |||
+ | <script type=" | ||
+ | new Stern(400, 300, 50, 150, 5); | ||
+ | |||
+ | class Stern extends Polygon { | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | super(true); | ||
+ | | ||
+ | for(int i = 0; i < 2 * zackenZahl; i++) { | ||
+ | |||
+ | | ||
+ | if(i % 2 == 0) r = rAußen; | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | |||
+ | } | ||
+ | |||
+ | setFillColor(Color.yellow); | ||
+ | | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | }</ | ||
+ | |||
+ | </ | ||
+ | |||
+ | </ | ||
+ | |||
+ | === UML-Diagramm zu " | ||
+ | {{ : | ||
+ | Auf dem nebenstehenden Diagramm habe ich die (sehr zahlreichen!) Attribute und Methoden der Klassen '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | |||
+ | === Viele Sterne === | ||
+ | Jetzt wollen wir unsere neue Klasse natürlich " | ||
+ | < | ||
+ | |||
+ | <div class=" | ||
+ | |||
+ | <script type=" | ||
+ | for(int i = 0; i < 15; i++) { | ||
+ | |||
+ | | ||
+ | | ||
+ | Stern s = new Stern(x, y, 10 + i, 30 + 3 * i, 5); | ||
+ | | ||
+ | | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | <script type=" | ||
+ | class Stern extends Polygon { | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | super(true); | ||
+ | | ||
+ | for(int i = 0; i < 2 * zackenZahl; i++) { | ||
+ | |||
+ | | ||
+ | if(i % 2 == 0) r = rAußen; | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | |||
+ | } | ||
+ | |||
+ | setFillColor(Color.yellow); | ||
+ | | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | }</ | ||
+ | |||
+ | </ | ||
+ | |||
+ | </ | ||
+ | |||
+ | ====== Beispiel 5: Feuerwerk ====== | ||
+ | Dieses Beispiel habe ich als Wiederholungsübung für meine zehnten Klassen im Schuljahr 2020/21 geschrieben. Damals war wegen er Corona-Epidemie das Sylvesterfeuerwerk ausgefallen. | ||
+ | {{ youtube> | ||
+ | < | ||
+ | <div class=" | ||
+ | <script type=" | ||
+ | new Feuerwerk(); | ||
+ | |||
+ | class Feuerwerk extends Actor { | ||
+ | |||
+ | | ||
+ | if(Math.random() < 0.03) { | ||
+ | |||
+ | int funkenzahl = Math.floor(Math.random() * 50 + 30); | ||
+ | int farbe = Color.randomColor(128); | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | new Funke(x, y, farbe, lebensdauer); | ||
+ | } | ||
+ | | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | class Funke extends Circle { | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | super(x, y, 4); | ||
+ | double winkel = Math.random() * 2 * Math.PI; | ||
+ | double v = Math.random() * 15 + 5; | ||
+ | vx = v * Math.cos(winkel); | ||
+ | vy = v * Math.sin(winkel); | ||
+ | setFillColor(farbe); | ||
+ | this.lebensdauer = lebensdauer; | ||
+ | } | ||
+ | |||
+ | | ||
+ | lebensdauer--; | ||
+ | move(vx, vy); | ||
+ | vy = vy + 0.2; | ||
+ | if(lebensdauer < 30) { | ||
+ | | ||
+ | } | ||
+ | if(isOutsideView() || lebensdauer < 0) { | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | </ |
wiederholung/vererbung.1669620501.txt.gz · Zuletzt geändert: 2022/11/28 07:28 von Martin Pabst