Benutzer-Werkzeuge

Webseiten-Werkzeuge


techniken:objektorientjava

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen gezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
techniken:objektorientjava [2016/07/06 11:26]
fbonowski [Methoden wirken lokal auf die Membervariablen des Objekts, mit dem sie aufgerufen werden]
techniken:objektorientjava [2016/07/14 14:43] (aktuell)
c.jaedicke [Konventionen]
Zeile 35: Zeile 35:
 </​code>​ </​code>​
 ==== Klassen können eigene Funktionen ("​Methoden"​ genannt) enthalten ==== ==== Klassen können eigene Funktionen ("​Methoden"​ genannt) enthalten ====
- 
 Schön wäre auch, wenn wir den Roboter mit einem einzigen Funktionsaufruf ein kleines Stück nach vorne gehen lassen könnten. Schön wäre auch, wenn wir den Roboter mit einem einzigen Funktionsaufruf ein kleines Stück nach vorne gehen lassen könnten.
  
Zeile 69: Zeile 68:
 myRobot = new Robot(); // erzeuge ein Objekt com Typ "​Robot"​ und speichere eine Referenz darauf in der "​myRobot"​ Variable myRobot = new Robot(); // erzeuge ein Objekt com Typ "​Robot"​ und speichere eine Referenz darauf in der "​myRobot"​ Variable
 </​code>​ </​code>​
 +
 +**Bei Arduino (C++) ist das anders: hier wird bereits bei der Deklaration eines Objekts eine Instanz erzeugt!**
 ==== Auf Membervariablen und Methoden eines Objekts kann mit dem "​."​ zugegriffen werden,==== ==== Auf Membervariablen und Methoden eines Objekts kann mit dem "​."​ zugegriffen werden,====
 Unser frischgebackenes Roboterobjekt können wir jetzt verwenden, um einen Roboter in Bewegung zu simulieren. Unser frischgebackenes Roboterobjekt können wir jetzt verwenden, um einen Roboter in Bewegung zu simulieren.
Zeile 96: Zeile 97:
 robotTwo.moveForward(1);​ // verändert die Variablen robotTwo.posX und robotTwo.posY robotTwo.moveForward(1);​ // verändert die Variablen robotTwo.posX und robotTwo.posY
 </​code>​ </​code>​
 +===== Referenzvariablen =====
 +==== In Java speichern Variablen nur Referenzen auf Objekte ====
 +Wenn ihr eine Variable mit einem Klassentyp deklariert (also z.B. unseren Roboter), dann wird in dieser Variable nicht etwa "das Objekt selbst"​ (also ein Wert) gespeichert,​ sondern nur "​welches Objekt mit dieser Variable gemeint ist" (also eine Speicheradresse).
  
-===== Konventionen ​=====+In der Praxis macht das insbesondere bei Zuweisungen von Variablen einen Unterschied:​ 
 +=== Bei primitiven Variablen... ​=== 
 +  * Wird der Inhalt der Variable kopiert.  
 +  * Beide Variablen haben danach getrennte Kopien des selben Wertes. 
 +  * Veränderungen der einen Variable haben nach einer Zuweisung keinen Einfluss auf den Wert der anderen Variable 
 +=== Bei Variablen mit Klassentyp... ​=== 
 +  * Wird nur die Referenz / Speicheradresse kopiert. 
 +  * Beide Variablen verweisen danach auf das **//​selbe//​** Objekt. 
 +  * Veränderungen des Objektes über die eine Variable wirken sich dementsprechend auf das aus, was über die andere Referenzvariable ausgelesen werden kann.
  
 +Hier ein Beispiel, welches das unterschiedliche Verhalten von Variablen mit primitiven und Klassentypen:​
 +<code Java>
 +//Primitive Variablen enthalten einen Wert, der bei Zuweisungen kopiert wird:
 +int a=1;
 +int b=2;
 +a=b;         // Der Inhalt von b (2) wird in a kopiert.
 +println(a); ​ // Ausgabe "​2"​
 +println(b); ​ // Ausgabe "​2"​
 +b=3;         // Der Inhalt von b wird mit "​3"​ überschrieben,​ a bleibt davon unberührt.
 +println(a); ​ // Ausgabe "​2"​ (unverändert)
 +println(b); ​ // Ausgabe "​3"​
  
-Bei der Benennung von Methoden sollte man sich an zwei grundsätzliche Konventionen halten:  +//Variablen mit Klassentyp enthalten eine Referenz auf ein Objekt
-  - Der Name der Methode fängt mit einem kleinen Buchstaben an und Namen welche mehrere Worte beinhalten fangen beim zweiten Wort mit einem Großbuchstaben an.  +Robot robotOne=new Robot(); // ein erster Roboter 
-  - Der Name sollte beschreiben wie die Methode mit dem Objekt interagiert.+Robot robotTwo=new Robot(); // ein zweiter Roboter
  
-Unsere Klasse bekommt zwei weitere Methoden, eine um den Roboter ​an seiner aktuellen Position zu zeichnen und eine um den Roboter um einen gewissen Winkel zu drehen.+robotOne.direction=PI; ​ // der erste Roboter ​schaut nach links 
 +robotTwo.direction=0; ​  // der zweite Roboter schaut nach rechts
  
-<code java> +robotOne=robotTwo;​ // RobotOne zeigt auch jetzt auf das Objekt, auf das vorher nur RobotTwo gezeigt hat. 
-class Robot { // Deklaration der Klasse Robot+// Das Objekt, auf das robotOne vorher gezeigt hat, wird vergessen. (und vom Garbage Collector entsorgt) 
 + 
 + 
 +robotTwo.direction=PI/​2;​ // Ändere die Richtung des Objekts, auf das die Referenz in robotTwo zeigt. 
 +println(robotOne.direction);​ // Da beide Variablen das gleiche Objekt referenzieren,​ kommt auch hier PI/2 heraus! 
 +</​code>​
  
-  int dRobot = 50;    //Der Durchmesser des Roboters in Pixel + 
-  float direction ​PI;  //Die Richtung ​in die der Roboter schaut ​ +===== Ein fertiges Programm ===== 
-                      //(PI (links), da der Winkel in Bogenmaß angegeben wird) +Zum Abschluss nochmal ein kleines Programm, ​in dem alles, was bisher passiert ist, angewandt wird: 
-  float posX = 100;   ​//Die x-Position des Roboters in Pixel + 
-  float posY = 100;   ​//Die y-Position des Roboters in Pixel +<code Java> 
-  ​+class Robot { // Deklaration ​der Klasse Robot 
 +  float posX = 100;     ​//Die x-Position des Roboters in Pixel 
 +  float posY = 100;     ​//Die y-Position des Roboters in Pixel 
 +  ​float direction= PI;  //Die Richtung in die der Roboter schaut, in Bogenmaß, gegen den Uhrzeigersinn,​ relativ zur X-Achse. 
 +                        // (PI  => der Roboter schaut nach links) 
 + 
   //Diese Methode zeichnet einen Roboter ​   //Diese Methode zeichnet einen Roboter ​
   //an seiner aktuellen Position und Ausrichtung.   //an seiner aktuellen Position und Ausrichtung.
   void drawRobot(){ //"​void"​ bedeutet dass es keinen Rückgabewert gibt   void drawRobot(){ //"​void"​ bedeutet dass es keinen Rückgabewert gibt
-    ​// Zeichne einen Kreis an der Position des Roboters. +    ellipse(posX,​posY,​20,20); // Zeichne ​einen Kreis an der Position ​des Roboters. 
-    ​ellipse(posX,​posY,​dRobot,dRobot); +    line(posX,​posY,​posX+cos(direction)*50,​ posY+sin(direction)*50);​// Zeichne eine Linie welche die Orientierung des Roboters angibt.
-    ​// Zeichne ​eine Linie welche die Orientierung ​des Roboters ​angibt+
-    line(posX,​posY,​posX+cos(direction)*50,​ posY+sin(direction)*50);​+
   }   }
-  ​+ 
   //Die moveForward-Funktion verändert die Position so, wie es einen Schritt nach vorne entspricht.   //Die moveForward-Funktion verändert die Position so, wie es einen Schritt nach vorne entspricht.
   void moveForward(float distance){   void moveForward(float distance){
Zeile 129: Zeile 161:
     posY = posY+sin(direction)*distance;​ // zugegriffen werden. (Sie sind im Objekt quasi "​lokal"​)     posY = posY+sin(direction)*distance;​ // zugegriffen werden. (Sie sind im Objekt quasi "​lokal"​)
   }   }
-  ​ 
-  //Diese Methode dreht den Roboter um einen gewissen Winkel ​ 
-  //welcher von "​winkelaenderung"​ vorgegeben wird. 
-  // Die Methode bekommt einen Übergabeparameter vom Typ "​float"​. 
-  void turnRobot(float angle){ ​ 
-    this. direction += angle; 
-  } 
-  ​ 
 } }
  
-</code>+Robot myRobot; ​// deklariere eine Referenz auf einen Roboter (sie verweist in diesem Moment ins Leere)
  
-Jetzt können wir die fertige Klasse verwenden. Um dies in Processing auf eine möglichst übersichtliche weise zu tun sollte ein neuer Tab geöffnet werden: 
  
-{{:​Techniken:​processingtab.jpg?​nolink|}}+// Das Processing "​setup"​ 
 +void setup(){ 
 +  myRobot=new Robot(); 
 +}
  
-In diesem neuen Tab speichert ihr eure Klasse. 
-===== Klasse verwenden in Processing ===== 
- 
-Klassen geben den Rahmen vor für unsere Objekte. Wie ihr bereits kennengelernt habt, kann man aus einer Klasse ein Objekt erzeugen durch den „new“ -Operator. 
-Ein Programm welches in Processing geschrieben wurde kann die "​Robot"​-Klasse z.B. folgendermaßen einsetzen: 
- 
-<code java> 
- 
-//Erstellt ein global verfügbares Objekt vom Typ "​Robot", ​ 
-//wie "​int"​ oder "​double",​ und geben ihm den Namen "​myRobot"​. 
-Robot myRobot; 
  
-void setup() { +// Das Processing ​"setup
-  ​// Festlegen der Fenstergröße +void draw(){ 
-  size(500,​500);​ +  background(235); ​      ​// Male den Hintergrund des Fensters neu an..
-  // Festlegen der Hintergrundfarbe +  myRobot.drawRobot(); ​  ​// Zeichne in das nun leere Fenster ​den Roboter 
-  background(235);​ +  myRobot.moveRobot(); ​  ​// Diese Funktion bewegt den Roboter ​ein wenig
-  //​Initialisiert das "Robot" ​Objekt +  myRobot.direction+=PI/​200; ​// drehe den Roboter ein Stück gegen den Uhrzeigersinn
-  myRobot = new Robot(); +
-+
- +
-void draw() { +
-  //Zu beginn jeder draw-Iteration wird das Fenster zurückgesetzt. +
-  background(235);​ +
-  ​//Das Robot-Objekt verfügt über eine Funktion die den Roboter malt+
-  myRobot.drawRobot();​ +
-  ​//Diese Funktion bewegt ​den Roboter ​ein wenig. +
-  myRobot.moveRobot();​ +
-  ​//Dieser Funktionsaufruf sorgt dafür das der Roboter ​nach jeder translation  +
-  //um PI/200 gedreht wird+
-  myRobot.turnRobot(PI/200);+
 } }
  
 </​code>​ </​code>​
  
-===== Klassen für Fortgeschrittene ​=====+===== Konventionen ​=====
  
-In diesem Abschnitt ist das Beispiel von oben nochmals aufgeführt in einer "​best-practise"​-Version. Hierbei ändern sich zwei wesentliche Dinge: 
  
-  - Statt einfachen Kommentaren werden die Konventionen ​der JavaDoc angewandt. Die JavaDoc ist eine Documentation des Codes welche automatisch aus den Kommentaren generiert wird sofern diese der vorgegebenen Konvention entspricht. Wie diese Konvention im Einzelnen aussieht erfahrt ihr z.B. hier[[https://​www.wecowi.de/​wiki/​Javadoc|https://​www.wecowi.de/​wiki/​Javadoc]]. +Bei der Benennung von Methoden sollte man sich an zwei grundsätzliche ​Konventionen ​halten:  
-  - Diese Version enthält Konstruktoren. Mit Konstruktoren können die Klassenvariablen direkt beim erstellen eines Objektes modifiziert werden. ​Der "​default"​-Konstruktor ist auch dann vorhanden wenn er nicht explizit definiert wurde, deshalb konnte in der einfachen Version ein Objekt erstellt werden ​mit //new Robot()//. In Java können Konstruktoren ​und Methoden im allgemeinen überladen werden. Das bedeutet es darf mehrere ​Methoden ​mit demselben Namen geben solange sich die Übergabeparameter bzw. Rückgabetyp unterscheiden. Im folgenden Beispiel sind zwei Konstruktoren enthalten.+  - Der Name der Methode fängt ​mit einem kleinen Buchstaben an und Namen welche ​mehrere ​Worte beinhalten fangen beim zweiten Wort mit einem Großbuchstaben an.  
 +  - Der Name sollte beschreiben wie die Methode mit dem Objekt interagiert.
  
-<code java> +Unsere ​Klasse ​bekommt zwei weitere Methoden, eine um den Roboter an seiner aktuellen Position zu zeichnen und eine um den Roboter um einen gewissen Winkel zu drehen.
-class Robot { // Deklaration der Klasse ​Robot+
  
-  /** Der Durchmesser des Roboters. */ +===== Tabs  in Processing ===== 
-  int dRobot; +Jetzt können wir die fertige Klasse verwendenUm dies in Processing auf eine möglichst übersichtliche weise zu tun sollte ​ein neuer Tab geöffnet werden:
-  /** Die Richtung in die der Roboter schaut. */ +
-  float winkel; +
-  /** Die x-Position des Roboters. */ +
-  float posX; +
-  /** Die y-Position des Roboters. */ +
-  float posY; +
-   +
-  /** +
-   * Der "​default"​-Konstruktor erstellt ein Roboter-Objekt mit Standardwerten für alle notwendigen Parameter. +
-   */ +
-  public Robot() { +
-    this.dRobot ​50; +
-    this.winkel ​PI; +
-    this.posX ​100; +
-    this.posY ​100; +
-  +
-  /** +
-   * Dieser Konstruktor erstellt ein Roboter-Objekt mit allen notwendigen Parametern,​ +
-   * entsprechend der Vorgabe durch die Eingabeparameter. +
-   */ +
-  public Robot(int dRobot, float winkel, float posX, float posY) { +
-    this.dRobot ​dRobot; +
-    this.winkel ​winkel; +
-    this.posX ​posX; +
-    this.posY ​posY; +
-  } +
-   +
-  /** +
-   * Diese Methode zeichnet einen Roboter an seiner aktuellen Position und Ausrichtung. +
-   */ +
-  void drawRobot(){ +
-    // Zeichne einen Kreis an der Position des Roboters. +
-    ellipse(posX,​posY,​dRobot,​dRobot);​ +
-    // Zeichne ​eine Linie welche die Orientierung des Roboters angibt. +
-    line(posX,​posY,​posX+cos(winkel)*50,​ posY+sin(winkel)*50);​ +
-  } +
-   +
-  /** +
-   * Diese Methode bewegt einen Roboter ​ein kleines Stück in die Richtung in die er gerade schaut. +
-   */ +
-  void moveRobot(){ +
-    this.posX = this.posX+cos(this.winkel)*2;​ +
-    this.posY = this.posY+sin(this.winkel)*2;​ +
-  } +
-   +
-  /** +
-   * Diese Methode dreht den Roboter um einen gewissen Winkel welcher von "​winkelaenderung"​ vorgegeben wird. +
-   */ +
-  void turnRobot(float winkelaenderung){ +
-    this.winkel = winkel + winkelaenderung;​ +
-  } +
-   +
-+
-</​code>​ +
-===== Referenzvariablen =====+
  
-Variablen welche stellvertretend für ein Objekt verwendet werden, z.B. myRobot aus dem vorherigen Bsp., stellen lediglich eine Referenz auf das Objekt dar. Man kann die Variable also auch als die Speicheradresse des Objektes verstehen. Dieser Sachverhalt ist insbesondere dann von Bedeutung wenn ein Objekt kopiert werden soll. Die "​best-practise"​ ist das Anlegen eines "​copy"​-Konstruktors in jeder Klasse, dieser überträgt alle Attribute des zu kopierenden Objektes in ein neues Objekt:+{{:​Techniken:​processingtab.jpg?​nolink|}}
  
-<code java>+In diesem neuen Tab speichert ihr eure Klasse. 
 +===== Das ist noch nicht alles... ===== 
 +Mit dem, was bis hierhin besprochen wurde, könnt ihr schonmal einigermaßen Ordunung in euer Programm bringen und die von einer Library bereitgestellen Klassen benutzen.
  
-class DummyBean { +Für ein vollständiges Verständnis von Objektorientierung in Java fehlen noch:
-  String dummy; +
-  int yummyDummy;+
  
-  ​DummyBean(DummyBean dummyBeanToCopy) { +  ​* Zugriffssteuerung auf Memberfunktionen und Variablen durch **//​private,​ public, protected//​** 
-    this.dummy = dummyBeanToCopy.dummy;​ +  ​* Vererbung
-    this.yummyDummy = dummyBeanToCopy.yummyDummy;​ +
-  ​+
-}+
  
-</code>+Eure Programme werden besser lesbar, wenn ihr die folgenden "​Style-Konventionen"​ einhaltet:​ 
 +[[http://​www.oracle.com/​technetwork/​java/​codeconventions-135099.html]]
  
-Und können diesen Konstruktor entsprechend aufrufen: 
- 
-<code java> 
-//A Object of my DummyBean class 
-DummyBean myFirstDummy = new DummyBean();​ 
-//make a copy of the myFirstDummy object 
-DummyBean mySecondDummy = new DummyBean(myFirstDummy);​ 
-</​code>​ 
- 
-Kopiert man Objekte nicht auf diese Weise sondern durch: 
- 
-<code java> 
-//A Object of my DummyBean class 
-DummyBean myFirstDummy = new DummyBean();​ 
-//silly copy 
-DummyBean mySecondDummy = myFirstDummy;​ 
-</​code>​ 
-, dann wirken sich Änderungen an "​myFirstDummy"​ auch auf "​mySecondDummy"​ aus da beide Variablen auf das selbe Objekt verweisen. 
-===== Vererbung ===== 
  
-In Java kann unter Vererbung eine Spezialisierung einer bestehenden Klasse verstanden werden. Wir unterscheiden dazu in Super- und Subklassen. Die Superklasse (oder Elternklasse) beinhaltet eher allgemeine Attribute und Methoden. Die Klasse "​Stift"​ könnte z.B. Attribute für Stiftlänge,​ Stiftfarbe, usw. enthalten. Die Subklasse bekommt von der Superklasse alle Attribute und Methoden vererbt, erweitert dieses Set aber um eigene Attribute und Methoden. Z.B. könnte die Subklasse "​Kugelschreiber"​ das Attribut Stift eingefahren/​Stift ausgefahren hinzufügen und eine Methode die diesen Zustand verändert. 
  
-Eine ausführliche Beschreibung wie Vererbung funktioniert findet ihr hier: [[http://​www.java-tutorial.org/​vererbung.html|http://​www.java-tutorial.org/​vererbung.html]] 
techniken/objektorientjava.1467797169.txt.gz · Zuletzt geändert: 2016/07/06 11:26 von fbonowski