Objekte und Klassen in Processing: Unterschied zwischen den Versionen

Aus ComeniusWiki
Wechseln zu: Navigation, Suche
 
Zeile 459: Zeile 459:
  
 
<popup name="Lösungsvorschlag Klassendiagramm">
 
<popup name="Lösungsvorschlag Klassendiagramm">
<syntaxhighlight lang="java">
+
 
 
[[Datei:Autofahrt.JPG]]
 
[[Datei:Autofahrt.JPG]]
</syntaxhighlight>
+
 
 
</popup>
 
</popup>
 +
 +
  
 
<popup name="Lösungsvorschlag">
 
<popup name="Lösungsvorschlag">

Aktuelle Version vom 5. Februar 2017, 18:30 Uhr

Am Ende des Kapitels solltest du

  • wissen, was ein Objekt ist,
  • wissen, was man unter objektorientierter Programmierung versteht,
  • den Begriff der Klasse verstehen,
  • das Konzept der Konstruktoren verstehen und anwenden können,
  • eigene Klassen schreiben können,
  • eigene kleine objektorientierte Programme modellieren und erstellen können.


Nachdem wir nun die meisten Grundkonzepte der Programmierung (Variablen, Bedingungen, Schleifen, Methoden) kennengelernt haben, wenden wir uns nun einer Denkweise zu, die eine andere Art der Strukturierung und Organisation von Programmen darstellt - der sogenannten objektorientierten Modellierung.

Unter Objektorientierung versteht man eine Modellierung komplexer Systeme, bei der ein System durch ein Zusammenspiel verschiedener Objekte beschrieben wird. Der Begriff Objekt ist dabei unscharf gefasst: ausschlaggebend an einem Objekt ist nur, dass ihm bestimmte Attribute (Eigenschaften) und Methoden zugeordnet sind und dass es in der Lage ist, von anderen Objekten Informationen zu empfangen beziehungsweise an diese zu senden. Objekte müssen dabei nicht gegenständlich (konkret) sein, sondern können auch mehr oder weniger abstrakt sein. Entscheidend dabei ist, dass das Grundkonzept der Objektorientierung (Objekte mit bestimmten Eigenschaften und Methoden) sinnvoll umgesetzt werden kann. Programmiertechnisch entspricht diesem Ansatz das Konzept der Klasse, in der Objekte aufgrund ähnlicher Eigenschaften zusammengefasst werden. Ein Objekt wird im Programmcode als Instanz einer Klasse definiert.


Inhaltsverzeichnis

Objekte

Bisher haben wir in Processing Objekte mit Hilfe vordefinierter Methoden erzeugt. Die große Stärke einer objektorientierten Programmiersprache besteht darin, dass wir als Programmierer eigene Datentypen in Form von Klassen nach unseren Vorstellungen und Bedürfnissen erstellen können, wodurch das Verhalten unserer Objekte deutlich flexibler gestaltet werden kann. Eine Klasse beschreibt entsprechend den Aufbau eines komplexen Datentyps.


Beispiele für Objekte der Klasse Rechteck:

Obj1.JPG

Wie wir bereits aus der 6.Klasse wissen, lassen sich diese Objekte der Klasse Rechteck auch in Form von Objektdiagrammen darstellen.

Klass1.JPG

Diese Darstellung von Objekten beinhaltet neben dem Objektnamen, der nach einer Konvention immer klein geschrieben wird, die Attribute des Objekts und die jeweiligen Attributwerte. Sie definieren den Zustand des Objekts. Objekte mit den denselben Attributen sind Instanzen einer Klasse. Eine Klasse stellt einen Konstruktionsplan für bestimmte Objekte dar, der mit all seinen Informationen auch ohne diese Objekte existiert. Eine Klasse ist also keine Menge von Objekten!


Die Definition einer Klasse beinhaltet drei Bestandteile:


  • Die Datenfelder bzw. Instanzvariablen speichern die Daten, die das jeweilge Objekt benutzt.
  • Die Konstruktoren erlauben es, neue Objekte zu erzeugen und diese in einen bestimmten Anfangszustand zu versetzen.
  • Die Methoden implementieren das Verhalten der Objekte.



Beispiel: Die Klasse Rechteck

Klass2.JPG

Instanzvariablen und Methoden haben wir bereits kennengelernt. Neu sind die sogenannten Konstruktoren.

Konstruktor

Eine Klasse kann keinen, einen oder mehrere unterschiedliche Konstruktoren besitzen. Sie dienen dazu, ein neu gebildetes Objekt einer Klasse in einen definierten Anfangszustand zu versetzen. Welcher dies ist hängt davon ab, welcher Konstruktor bei der Objektbildung aufgerufen wird. Ein leerer (Standard-) Konstruktor muss nicht angegeben werden, er wird bei Fehlen von der JVM (Java Virtual Machine) automatisch erzeugt. Aus diesem Grund hatten wir in unseren bisherigen Aufgaben keinen expliziten Konstruktor.

Syntax:

nameDerKlasse(Parameter) {}

Beispiel: Konstruktoren der obigen Klasse Rechteck:

Rechteck() weist dem Rechteck standardmäßig Werte zu.

Rechteck(){
breite = 10;
hoehe = 7;
}

Wir erhalten bei Aufruf des Konstruktors ein Rechteck der Größe 10x7. Die restlichen Werte werden von der JVM auf einen internen Standardwert gesetzt.


Rechteck(breite, hoehe) gibt dem User die Möglichkeit, die Größe des Rechtecks selbst zu bestimmen.


Rechteck(int breite, int hoehe){
this.breite = breite;
this.hoehe = hoehe;
}

Hier werden nach Aufruf des Konstruktors den Instanzvariablen die entsprechenden Werte der Parameter zugewiesen. Das Schlüsselwort this liefert innerhalb eines Objekts immer eine Referenz auf das Objekt selbst, d.h. es steht in der bekannten Punktschreibweise an der Stelle des Objektnamens einfach das Wort this.


Rechteck(breite, hoehe, fuellfarbe) gibt dem User die Möglichkeit, neben der Größe des Rechtecks auch noch dessen Füllfarbe festzulegen.


Rechteck(int breite, int hoehe, color fuellfarbe){
this.breite = breite;
this.hoehe = hoehe;
this.fuellfarbe = fuellfarbe
}

Konstruktoren können also mit unterschiedlichen Parameterlisten deklariert sein. Man spricht hier vom Überladen des Konstruktors.

Konstruktoraufruf

Neue Instanzen einer Klasse werden mit dem Operator new erzeugt.

Rechteck rechteck1 = new Rechteck();
 
Rechteck rechteck2 = new Rechteck(12, 8);
 
Rechteck rechteck3 = new Rechteck(15, 4, color(255, 0, 0));


Die drei erzeugten Rechtecke sind vom Typ Rechteck; d.h. sie sind Instanzen der Klasse Rechteck.

rechteck1 wird mit dem Standardkonstruktor erzeugt und hat die Größe 10x7.
rechteck2 wird vom User auf die Größe 12x8 festgelegt
rechteck3 bekommt vom User die Größe 15x4 und die Füllfarbe rot zugewiesen.


Hier sollte nun deutlich werden, dass das erzeugte Objekt eine Variable ist, die nach dem Plan der Klasse Rechteck aufgebaut ist. Erst wenn das Objekt erzeugt wurde, kann mittels Punktschreibweise auch auf die Eigenschaften des Objekts zugegriffen werden. Beispiel:

rechteck1.breite = 10; 
 
rechteck3.fuellfarbe = color(0, 255, 0);



Sehen wir uns nun ein Processing-Programm mit einer Klasse in Aktion an.

Zuerst die Klasse (Klassen immer in einen neuen Tab schreiben):

class Rechteck{
 
  //Attribute
 
  int xPos; 
  int yPos;
  int laenge;
  int breite;
  int linienbreite;
 
  //Farben können wir mit dem Datentyp color darstellen
  color linienfarbe = color(255, 0, 0);
  color fuellfarbe = color(255, 255, 0);
 
 
  //Konstruktoren
 
  Rechteck(){
    xPos = 100;
    yPos = 100;
    laenge = 100;
    breite = 50;
  }
 
  Rechteck(int laenge, int breite, color fuellfarbe){
    xPos = width/2;
    yPos = height/2;
    this.laenge = laenge;
    this.breite = breite;
    this.fuellfarbe = fuellfarbe;
  }
 
 
//Methoden
 
  void display(){
    stroke(linienfarbe);
    fill(fuellfarbe);
    rect(xPos, yPos, laenge, breite);
  }
 
  void move(int v){
    xPos = xPos + v;
    if(xPos>width){xPos = 0; fuellfarbe = color(random(256), random(256), random(256));};
  }
 
}


Nun können wir innerhalb des (Haupt)-Programms auf den neuen Datentyp zugreifen:


Rechteck r1;
Rechteck r2;
 
void setup(){
  size(500, 300);
  r1 = new Rechteck(100, 50, color(255,0, 0));
  r2 = new Rechteck(100, 50, color(255, 255, 0));
}
 
void draw(){
  background(0);
  r1.display();
  r1.move(2);
 
  r2.display();
  r2.move(3);
}


Aufgabe 1

a) In einem kleinen Programm wollen wir eine Anzahl von Blasen aufsteigen lassen. Erstelle dazu eine Klasse Blase mit einem Konstruktor, mit dem wir Blasen unterschiedlicher Größe erzeugen können, die vom unteren Rand des Zeichenfensters aufsteigen. Eine Methode display() ist für die Darstellung der Blase zuständig, eine Methode aufsteigen() für das Aufsteigen. Dabei soll die Geschwindigkeit über einen Parameter festgelegt werden. Erzeuge anschließend im Hauptprogramm vier Blasen unterschiedlicher Größe, die mit unterschiedlicher Geschwindigkeit nach oben steigen.



b) Modifiziere die Methode aufsteigen() so, dass weitere Blasen von einer beliebigen Stelle am Boden und mit veränderter Geschwindigkeit aufsteigen.



Aufgabe 2 ("UFO-Attack")

Wir wollen nun Bewegung in unsere UFOs aus Aufgabe 2 im letzten Kapitel bringen. Wir brauchen dazu eine Klasse Ufo, die das Erzeugen der UFO-Objekte ermöglicht. Sie beinhaltet neben dem Konstruktor eine Methode display() zum Darstellen der Objekte und eine Klasse move() zum Bewegen der UFOs. Der Konstruktor sollte dabei einen Parameter enthalten, mit dem die move()-Funktion die UFOs in unterschiedliche Richtungen lenkt. Im Hauptprogramm bauen wir unsere Ufo-Armee aus einzelnen UFOs zusammen. Es reichen dabei 3 bis 5 UFOs um den Eindruck eines ganzen Schwarms zu erzeugen.




Exkurs: UML

Die Unified Modeling Language (Vereinheitlichte Modellierungssprache), kurz UML, ist eine grafische Modellierungssprache zur Spezifikation, Konstruktion und Dokumentation von Software-Teilen und anderen Systemen. Sie ermöglicht die allgemein verständliche Darstellung sowohl statischer als auch dynamischer Aspekte eines Systems. UML-Diagramme lassen sich in Strukturdiagramme und Verhaltensdiagramme unterteilen, wobei man insgesamt sieben Struktur- und sieben Verhaltensdiagramme unterscheiden kann. Für jeden dieser Diagrammtypen existiert eine standardisierte Notation.

Klassendiagramm

Klassendiagramme stellen das zentrale Konzept der UML dar. Sie zeigen die statischen Bestandteile und Attribute von Systemen und welche Beziehungen sie untereinander einnehmen können. Bis auf die Definition von Operatoren der Klassen werden jegliche dynamischen Aspekte außer Acht gelassen.

Notation

Klasse

Das Notationselement einer Klasse wird in drei Abschnitte aufgeteilt:

Klassendiagramm.JPG


Attribut

Die Attribute beschreiben die Daten, die von den Objekten einer Klasse angenommen werden können. Jedes Attribut hat einen bestimmten Datentyp. Alle Objekte einer Klasse haben dieselben Attribute, können aber unterschiedliche Attributwerte besitzen.

Sichtbarkeit: Dieses Merkmal weist die Zugriffsrechte zu. Wir werden in JAVA zuerst public (+) und private (-) kennenlernen. Attribute können gemäß dem Geheimnisprinzip der objektorientierten Programmierung nur über vordefinierte Schnittstellen (Getter und Setter, d.h. Methoden, die die Attributwerte zurückliefern bzw. verändern) gelesen und geändert werden. (siehe Datenkapselung). Aus diesem Grund werden wir die Sichtbarkeit von Attributen bis auf weiteres auf private setzen.


Assoziation

Eine Assoziation beschreibt eine Beziehung zwischen zwei oder mehr Klassen. Üblicherweise umfassen Java-Programme mehr als nur eine Klasse, zwischen denen bestimmte Beziehungen bestehen. Bei der Modellierung legen wir diese Assoziationen fest und setzen sie dann bei der Implementierung um. Im Klassendiagramm legen wir die Assoziation durch eine Linie zwischen den entsprechenden Klassen fest, geben einen Assoziationsnamen mit entsprechender Leserichtung an und legen die Multiplizität fest, d.h. die mögliche Anzahl der an der Beziehung beteiligten Objekte.


Assoziation.JPG


Aufgabe 3


Wir wollen ein Programm erstellen, in dem ein kleines Auto vor der Kulisse eines Dorfes aus Häusern und Bäumen vorbeifährt. Erstelle zuerst die entsprechenden Klassendiagramme für die Klassen Haus, Baum und Auto und stelle das Hauptprogramm als eigene Klasse Autofahrt dar. Gib auch die entsprechenden Assoziationen an.