Benutzer-Werkzeuge

Webseiten-Werkzeuge


g9:uebungen:vererbung:start

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen RevisionVorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
g9:uebungen:vererbung:start [2021/01/20 17:49] – [Fachbegriffe] Martin Pabstg9:uebungen:vererbung:start [2022/07/01 07:46] (aktuell) – [Beispiel 7: Fraktaler Baum] Martin Pabst
Zeile 1: Zeile 1:
 ====== Vererbung ====== ====== Vererbung ======
-Wir haben Klassen bisher als Mittel zur Schaffung übersichtlichen Codes kennengelerntMit ihrer Hilfe werden zusammmengehörige Daten gebündelt und mit den Methoden verwoben, die auf ihnen operieren. In diesem Kapitel lernen wir, wie Klassen uns helfen, Doppelungen im Code zu vermeiden. Sie helfen uns, bereits existierenden Code - auch den anderer Programmierer - einfach zu erweitern.+====== Beispiel 1Advanced Robot ======
  
-====== Beispiel 1: Erweiterung der Buntstift-Klasse ====== +<WRAP center round todo 80%> 
-Erinnert Ihr Euch an die Buntstift-Klasse aus dem [[klassen2:constructors:start|Kapitel über Konstruktoren]]? Wir wollen eine ''StiftNeu''-Klasse erstellendie nicht nur farbig schreiben kann, sondern wahlweise - auch in GroßschriftDazu wollen wir die Klasse ''Buntstift'' verwendenohne sie zu verändern +Die Klasse Robot hat alle Methoden, die Du von Robot Karol her kennst. Erweitere sie um weitere Methoden: 
- \\ \\ +  * Die Methode ''umdrehen()'' soll bewirken, dass der Roboter sich um 180° dreht. 
 +  * Die Methode ''gehe(int schrittzahl)'' soll bewirken, dass der Roboter mehrere Schritte geht. 
 +  * Die Methode ''legeBahn(int länge)'' soll bewirken, dass der Roboter eine Bahn von Ziegeln der angegebenen Länge legt. 
 +  * Die Methode ''legeQuadrat(int seitenlänge)'' soll bewirkendass der Roboter ein nicht-ausgefülltes Quadrat der angegebenen Seitenlänge mit der Höhe 1 baut. 
 +  * Die Methode ''baueTreppe(int höhe)'' soll bewirkendass der Roboter eine Treppe der angegebenen Höhe baut.
  
-<WRAP center round info 60%> +Lass Dir noch weitere Methoden einfallen und schreibe ein Hauptprogramm, das die Methoden nutztum eine große Burg zu bauen!
-Warum stellen wir die erschwerende Forderung an unsdie Klasse ''Buntstift'' nicht zu verändern? Das wäre doch der einfachste Weg! +
-  - 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 ''Buntstift'' zwei verschiedene erweiterte Klassen erstellen. Dann haben wir im fertigen Programm den Programmcode der Klasse ''Buntstift'' dreimal in sehr ähnlicher Ausprägung im Arbeitsspeicher. Und falls im Programmcode der Klasse ''Buntstift'' ein Fehler gefunden wird, müssten wir ihn an drei verschiedenen Stellen verbessern.  +
 </WRAP> </WRAP>
- 
-In einem ersten Schritt erstellen wir die Klasse ''StiftNeu'' ohne Inhalt, geben bei der Klassendefinition aber an:  
-<code learnj> 
-class StiftNeu extends Buntstift { 
-} 
-</code> 
  
  
 <HTML> <HTML>
  
-<div class="java-online" style="height: 400px; width: 100%" data-java-online="{'withBottomPanel': false, 'id': 'Vererbung1'}">+<div class="java-online" style="height: 400px; width: 100%" data-java-online="{'withBottomPanel': false, 'id': 'Vererbung0'}">
  
-<script type="text/plain" title="Buntstift.java"> +<script type="text/plain" title="AdvancedRobot.java"> 
-StiftNeu stift = new StiftNeu(Color.red); +AdvancedRobot tom = new AdvancedRobot(1, 1, 10, 10); 
-stift.schreibe("Hallo Welt");+tom.legeQuadrat(4); 
 +tom.baueTreppe(3);
  
-class StiftNeu extends Buntstift {+class AdvancedRobot extends Robot { 
 +    
 +   void umdrehen() { 
 +      linksDrehen(); 
 +      linksDrehen(); 
 +   }
  
-+   void gehe(int schrittzahl) 
- +      for (int i = 0i < schrittzahl; i++) { 
-class Buntstift +         schritt(); 
- +      }
-   Color farbe+
- +
-   public Buntstift(Color farbe1{ +
-      farbe = farbe1;+
    }    }
  
-   public void schreibe(String text) { +   void legeBahn(int länge) { 
-      println(text, farbe);+      for (int i = 0; i < länge; i++) { 
 +         hinlegen(); 
 +         schritt(); 
 +      }
    }    }
  
-}</script> +   void legeQuadrat(int seitenlänge) { 
- +      for (int s = 04s++{ 
-</div> +         legeBahn(seitenlänge); 
- +         linksDrehen();  
-</HTML> +      }
-  * Führe das Programm Schrittweise mit "step into ({{:klassen2:constructors:step-into-dark.png?nolink|}})" aus. Wieso führt der Aufruf ''stift.schreibe("Hallo Welt!")'' nicht zu einem Fehler, obwohl die Klassendefinition der Klasse ''StiftNeu'' (Zeile 4 - 6) doch ganz leer ist? +
-  * Lass die Maus auf den Bezeichner ''StiftNeu'' im Programm kurz verharren bis sich der Tooltip mit der Klassendefinition öffnet. Woher kommen die ganzen Attribute und Methoden? +
- +
-<WRAP center round info 60%> +
-Mithilfe des Schlüsselwortes ''extends'' kann man eine neue Klasse erstellen, die **alle Methoden und Attribute** einer anderen Klasse **"erbt"**. Im Beispiel sorgt die Definition +
-<code learnj [enable_line_numbers="true", start_line_numbers_at="4"]> +
-class StiftNeu extends Buntstift +
- +
-+
-</code> +
-dafür, dass die Klasse ''StiftNeu'' alle Methoden und Attribute der Klasse ''Buntstift'' enthält. \\ \\  +
-Die neue Klasse, die von der bestehenden Klasse erbt, nennt man **Unterklasse**, die andere **Oberklasse**. Wegen er englischen Fachbegriffe **child class** und **parent class** sind auch die Begriffe **Kindklasse** und **Elternklasse** gebräuchlich. +
-</WRAP> +
- +
-Wir haben bisher also eine "Kopie" der Klasse ''Bunstift'' erstellt. Jetzt wird'interessant: Wir erweitern die Klasse ''StiftNeu'', indem wir in die Klassendefinition zusätzliche Attribute und Methoden setzen: +
- +
-<HTML> +
-<div class="java-online" style="height: 500pxwidth: 100%" data-java-online="{'withBottomPanel': true, 'id': 'Vererbung2'}"> +
-<script type="text/plain" title="StiftNeu.java"> +
-StiftNeu stiftGroß = new StiftNeu(Color.red, true); +
-stiftGroß.schreibe("Hallo Welt"); +
- +
-StiftNeu stiftKlein = new StiftNeu(Color.lime, false); +
-stiftKlein.schreibe("Hallo Welt"); +
- +
-class StiftNeu extends Buntstift { +
-    +
-   boolean großschreibung; +
- +
-   public StiftNeu(Color farbe, boolean großschreibung) { +
-      super(farbe); +
-      this.großschreibung = großschreibung;+
    }    }
  
-   public void schreibe(String text) { +   void baueTreppe(int höhe) { 
-      if(großschreibung) { +      for (int i = 0; i < höhe; i++) { 
-         text = text.toUpperCase();+         legeBahn(höhe - i); 
 +         umdrehen(); 
 +         gehe(höhe - i - 1); 
 +         umdrehen();
       }       }
-      super.schreibe(text); 
    }    }
 } }
 </script> </script>
-<script type="text/plain" title="Buntstift.java"> 
-class Buntstift { 
- 
-   Color farbe; 
- 
-   public Buntstift(Color farbe1) { 
-      farbe = farbe1; 
-   } 
- 
-   public void schreibe(String text) { 
-      println(text, farbe); 
-   } 
- 
-}</script> 
- 
-</div> 
- 
 </HTML> </HTML>
-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 ''StiftNeu'' an: 
-<code learnj [enable_line_numbers="true", start_line_numbers_at="11"]> 
-   public StiftNeu(Color farbe, boolean großschreibung) { 
-      super(farbe); 
-      this.großschreibung = großschreibung; 
-   } 
-</code> 
-Da ''StiftNeu'' alle Methoden und Attribute (also die gesamte Funktionalität) der Klasse ''Buntstift'' erbt, muss sichergestellt werden, dass beim Erzeugen von ''StiftNeu''-Objekten immer ein Konstruktor der Klasse ''Buntstift'' aufgerufen wird. Das erledigen wir durch den Aufruf ''super(farbe)''. ''super'' steht dabei immer für die gleichnamige Methode der Oberklasse. 
-<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 ''super'' erreicht. 
-</WRAP> 
- 
-==== Überschreiben von Methoden ==== 
-{{ :klassen2:inheritance:pasted:20200510-110250.png}} 
-Die Methode ''public void schreibe(String text)'' hat **dieselbe Signatur** (d.h. Bezeichner, Parametertypen und Typ des Rückgabeparameters) **wie die gleichnamige Methode der Oberklasse** ''Buntstift''. Nach außen hin ist daher nur noch diese neue Methode sichtbar, nicht mehr die der Klasse ''Buntstift''. Man sagt: Die Methode **überschreibt** die gleichnamige Methode der Oberklasse. In der Methode selbst können wir die gleichnamige Methode der Oberklasse aber durchaus aufrufen. Dazu benutzen wir wieder das Schlüsselwort ''super'': 
- 
-<code learnj [enable_line_numbers="true", highlight_lines_extra="5", start_line_numbers_at="16"]> 
-   public void schreibe(String text) { 
-      if(großschreibung) { 
-         text = text.toUpperCase(); 
-      } 
-      super.schreibe(text); 
-   } 
-</code> 
- 
-  * Führe das Programm oben wieder schrittweise mit "step into ({{:klassen2:constructors:step-into-dark.png?nolink|}})" aus und achte genau darauf, wann Code aus der Unterklasse ''StiftNeu'' ausgeführt wird und wann Code aus der Oberklasse ''Buntstift''. 
- 
-==== UML-Diagramm ==== 
-Rechts siehst Du das UML-Diagramm der Klassen. Die Vererbung wird durch eine Linie von ''StiftNeu'' zu ''Bunststift'' symbolisiert, die in einen "Pfeil" in Dreiecksform mündet.  \\  \\  
-**Erinnerung:** Die durch die Raute symbolisierte Relation von ''Buntstift'' zu ''Color'' ist eine Aggregation: Die Klasse ''Buntstift'' besitzt nämlich ein Attribut ''farbe'' der Klasse ''Color''. 
- 
  
 ====== Beispiel 2: Fliegende Rechtecke ====== ====== Beispiel 2: Fliegende Rechtecke ======
-{{ youtube>jG5qlZYm6W0?large }} 
 Starte das Programm und regle die Geschwindigkeit langsam hoch! Starte das Programm und regle die Geschwindigkeit langsam hoch!
 <HTML> <HTML>
Zeile 156: Zeile 73:
    new FlyingRectangle();    new FlyingRectangle();
 } }
- 
- 
  
 class FlyingRectangle extends Rectangle { class FlyingRectangle extends Rectangle {
Zeile 187: Zeile 102:
 </HTML> </HTML>
  
-Damit die Seite nicht zu lange wird, findest Du die [[.flyingRectangle:start|ausführliche Erklärung dieses Programms auf einer extra Seite]].+Damit die Seite nicht zu lange wird, findest Du die [[:klassen2:inheritance:flyingRectangle:start|ausführliche Erklärung dieses Programms auf einer extra Seite]].
  
 === UML-Diagramm zu "Fliegende Rechtecke" === === UML-Diagramm zu "Fliegende Rechtecke" ===
Zeile 273: Zeile 188:
 </HTML> </HTML>
  
-[[.starfieldloesung:start|Lösung zur Aufgabe "Starfield"]]+[[:klassen2:inheritance:starfieldloesung:start|Lösung zur Aufgabe "Starfield"]]
  
 ====== Beispiel 3: Klasse "Raute" ====== ====== Beispiel 3: Klasse "Raute" ======
Zeile 427: Zeile 342:
 </HTML> </HTML>
  
-===== Feuerwerk =====+===== Beispiel 5: Feuerwerk =====
 Das Beispiel "Feuerwerk" [[:api:documentation:grafik:animation#beispiel_4feuerwerk|findest Du hier]]. Das Beispiel "Feuerwerk" [[:api:documentation:grafik:animation#beispiel_4feuerwerk|findest Du hier]].
  
 +
 +====== Beispiel 6: Kochkurve ======
 +<HTML>
 +
 +<div class="java-online" style="height: 400px; width: 100%" data-java-online="{'withBottomPanel': false, 'id': 'Kochkurve'}">
 +
 +<script type="text/plain" title="Kochkurve.java">
 +new World(1000, 1000);
 +Kochkurve k = new Kochkurve(7);
 +
 +class Kochkurve extends Turtle {
 +   
 +   public Kochkurve(int tiefe) {
 +      super(50, 700);
 +      setBorderWidth(3); 
 +      int länge = 700;
 +      turn(60);
 +      zieheLinie(länge, tiefe);
 +      turn(-120);
 +      zieheLinie(länge, tiefe);
 +      turn(-120);
 +      zieheLinie(länge, tiefe);
 +   }
 +   
 +   public void zieheLinie(double länge, int tiefe) {
 +      if(tiefe == 0) {
 +         forward(länge);
 +         return;
 +      }
 +
 +      zieheLinie(länge / 3, tiefe - 1);
 +      turn(60);
 +      zieheLinie(länge / 3, tiefe - 1);
 +      turn(-120);
 +      zieheLinie(länge / 3, tiefe - 1);
 +      turn(60);
 +      zieheLinie(länge / 3, tiefe - 1);
 +
 +   }
 +
 +}
 +</script>
 +
 +</div>
 +
 +</HTML>
 +
 +
 +====== Beispiel 7: Fraktaler Baum ======
 +<HTML>
 +
 +<div class="java-online" style="height: 400px; width: 100%" data-java-online="{'withBottomPanel': false, 'id': 'Baum'}">
 +
 +<script type="text/plain" title="Baum.java">
 +new FraktalerBaum(400, 600, 0.7, 9, 35);
 +
 +class FraktalerBaum extends Turtle {
 +   
 +   double faktor;
 +   double winkel;
 +   
 +   FraktalerBaum(double x, double y, double faktor, int tiefe, double winkel) {
 +      super(x, y);
 +      this.faktor = faktor;
 +      this.winkel = winkel;
 +      setBorderWidth(2);
 +      turn(90);
 +      zeichneAst(tiefe, 180);
 +   }
 +
 +   void zeichneAst(int n, double länge) {
 +      if(n == 0) return;
 +
 +      forward(länge);
 +      turn(winkel);
 +      zeichneAst(n - 1, länge * faktor);
 +      turn(-2*winkel);
 +      zeichneAst(n - 1, länge * faktor);
 +      turn(winkel);
 +      turn(180);
 +      penUp();
 +      forward(länge);
 +      turn(180);
 +      penDown();
 +   }
 +
 +}
 +
 +</script>
 +
 +</div>
 +
 +</HTML>
g9/uebungen/vererbung/start.1611161382.txt.gz · Zuletzt geändert: 2021/12/29 11:29 (Externe Bearbeitung)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki