Javakurs für Anfänger Einheit 09: Mehr zur Objektorientierung Lorenz Schauer Lehrstuhl für Mobile und Verteilte Systeme Heutige Agenda 1. Teil: Weitere Aspekte der Objektorientierung Klassen Variablen Das Schlüsselwort static Beispiel: Instanzzähler Klassen Methoden Unveränderliche Attribute (Konstanten) 2. Teil: Vererbung Das Schlüsselwort extends Beispiel: Student und Person Subtyping und Type casting Praxis: Klasse Student anpassen Übung mit Vererbung Weihnachtsbeispiel Lernziele Unterschiede zwischen Instanz- und Klasseneigenschaften verstehen Einführung der Schlüsselwörter: static und final Konzept der Vererbung kennenlernen und verstehen 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 2 Klassenvariablen So wie es Instanzvariablen gibt, die zu einer gewissen Instanz (Objekt) gehören und deren Attribute speichern, so gibt es aus Klassenvariablen: Speichern Werte für eine ganze Klasse Sprich: Eine Änderung wirkt sich auf alle Objekte der Klasse aus! Beschreiben keine objektspezifischen Eigenschaften Werden auch als statische Attribute bezeichnet Eingeleitet mit dem Schlüsselwort static Bsp.: static int instances; Statische Attribute können, wie Instanzvariablen auch public, private, oder protected sein Auf Klassenvariablen kann (je nach Sichtbarkeit) auch zugegriffen werden, selbst wenn kein Objekt existiert Über: Klassenname.klassenvariable; Bsp.: Auto.instances; Zugriff über ein direktes Objekt ist auch möglich Über: objektname.klassenvariable; Bsp.: fiat.instances; Sollte allerdings vermieden werden 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 3 Anwendung für Klassenvariablen Ein bekanntes Beispiel für die Anwendung von Klassenvariablen stellt ein Instanzzähler dar: // Beispiel für einen Instanzzähler über Klassenvariablen public class Auto { //Klassenvariable public static int instances; //Instanzvariablen private String name; private int preis; //Konstruktor public Auto(String name, int preis){ this.name = name; this.preis = preis; // Klassenvariable instances wird im Konstruktor erhöht Auto.instances++; } } //Weitere Methoden… 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 4 Anwendung für Klassenvariablen Zugriff auf die Klassenvariable: public class Autohaus { public static void main(String[] args) { System.out.println("Willkommen im Autohaus!"); System.out.println(" Es sind bereits "+Auto.instances+" Autos erzeugt worden!"); Auto fiatPunto = new Auto("fiatPunto", 9000); Auto mercedes = new Auto("Mercedes",30000); System.out.println("Es sind bereits "+Auto.instances+" Autos erzeugt worden!"); } } Ausgabe: Willkommen im Autohaus! Es sind bereits 0 Autos erzeugt worden! Es sind bereits 2 Autos erzeugt worden! 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 5 Klassenmethoden Neben den Klassenvariablen gibt es natürlich auch Klassenmethoden: Gehören zur Klasse und nicht zu den Objekten Können daher NUR auf Klassenvariablen arbeiten und NICHT auf Instanzvariablen operieren! Beschreiben also kein Objektverhalten und manipulieren daher auch keine Instanzvariablen Können nur Statische Methoden aufrufen Die Verwendung von this ist nicht möglich, da kein Objekt zugeordnet ist! Können direkt auf Klassen aufgerufen werden auch ohne, dass ein Objekt der Klasse existiert Beispiele: Main-Methode: public static void main(String[] args) Wird beim Programmstart aufgerufen, an dem noch keine Objekte existieren public static int getInstances() {return Auto.instances}; Das Aufrufen über Objekte ist auch möglich, aber unerwünscht! 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 6 Anwendung für Klassenmethoden Leichte Veränderung des Beispiels von vorher: // Beispiel für einen Instanzzähler über private Klassenvariablen public class Auto { //Klassenvariable private static int instances; //Instanzvariablen private String name; private int preis; //Konstruktor public Auto(String name, int preis){ this.name = name; this.preis = preis; // Klassenvariable instances wird im Konstruktor erhöht Auto.instances++; } //Weitere Methoden… } // Statischer Getter für statische Variable public static int getInstances(){ return Auto.instances; } 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 7 Anwendung für Klassenmethoden Zugriff auf die Klassenvariable nun über den statischen Getter: public class Autohaus { public static void main(String[] args) { System.out.println("Willkommen im Autohaus!"); System.out.println(" Es sind bereits "+Auto.getInstances()+" Autos erzeugt worden!"); Auto fiatPunto = new Auto("fiatPunto", 9000); Auto mercedes = new Auto("Mercedes",30000); System.out.println("Es sind bereits "+Auto.getInstances()+" Autos erzeugt worden!"); } } Ausgabe: Willkommen im Autohaus! Es sind bereits 0 Autos erzeugt worden! Es sind bereits 2 Autos erzeugt worden! 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 8 Unveränderliche Attribute (Konstanten) Ein Anwendungsfall für statische Attribute sind Konstanten, die ihren Initialwert nicht mehr verändern können. Beispiele für bekannte Konstanten: Math.PI, Math.E Wir können Konstanten, die eine Klasse anbieten soll selbst definieren: Mit dem Schlüsselwort final Sollten nach Konvention in GROßBUCHSTABEN deklariert werden Sollten public sein, um direkt von Außen darauf zugreifen zu können // Beispiel für eigene Konstanten // Konstanten benutzen public class MeineKlasse{ public static final int MAX_VALUE = 10; int max_wert = MeineKlasse.MAX_VALUE; public static final double MEIN_WERT = 1.2; public static final double PI = 3.14; for(int i=0;i<MeineKlasse.MAX_VALUE;i++) { // Do something… } //Weitere Attribute und Methoden } 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 9 Unveränderliche Attribute Mit final lassen sich auch Instanzvariablen deklarieren, die nur einmal mit einem Wert belegt werden dürfen, der sich danach nicht mehr verändern lässt Das kann sehr nützlich sein, wenn sich Initialbelegungen von Objekten nicht mehr ändern dürfen Beispiel: Der Vorname eines Menschen ändert sich nicht mehr. public class Mensch{ private final String vorname; private String name; // Einmalige Belegung durch Konstruktor erlaubt public Mensch(String vorname, String name){ this.vorname = vorname; this.name = name; } //Aber kein Setter für vorname erlaubt! } 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 10 Kleine Programmieraufgabe Nutzen Sie nun Ihre Klasse Student aus der letzten Stunde und verändern Sie die Klasse wie folgt: Fügen Sie einen Instanzzähler ein, welcher es mittels einer Klassenvariablen und einer entsprechenden Getter-Methode erlaubt, die Anzahl der erzeugten Instanzen zu zählen und widerzugeben. Ändern Sie nun die Instanzvariable „matrikelnr“, so dass diese nur einmal mit einem Wert belegt werden darf. Prüfen Sie nun in Ihrem Programm (Main-Methode) den Instanzzähler und lassen Sie sich die Anzahl der erzeugten Studenten ganz am Anfang und am Ende Ihres Programms ausgeben. 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 11 Teil 2: Vererbung Die Vererbung ist ein Kernprinzip der objektorientierten Programmierung Motivation: Wiederverwendbarkeit von Klassen Neue Klassen müssen nicht immer komplett neu geschrieben werden! Oft reicht es aus, neue Klassen aus bestehenden abzuleiten => Vererbung Neue Klasse übernimmt die Eigenschaften und das Verhalten der alten Klasse Die neue Klasse wird auch als Sub-, Unter-, oder Kindklasse bezeichnet Die alte Klasse wird auch als Super-, Ober-, Basis-, Wurzel-, oder Vaterklasse bezeichnet Die Unterklasse kann weitere Attribute und Methoden definieren Person Die Unterklasse kann Methoden der Oberklasse überschreiben oder erweitern Vererbung stellt eine „is-a“ Beziehung dar. Ein Objekt der Unterklasse ist damit auch ein Objekt der Oberklasse Bsp.: Ein Student ist auch eine Person 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer Student 12 Das Schlüsselwort extends Eine Vererbung („is-a“-Beziehung) wird mit dem Schlüsselwort extends in der Kopfzeile der Unterklasse nach dem Klassennamen eingeleitet Beispiel: Person und Student: Person hat einen Namen, und einen Vornamen Person implementiert Getter- und Setter Methoden für name und vorname Student hat darüber hinaus noch eine Matrikelnummer Student implementiert nur noch die Getter- und Setter Methoden für matrikelnummer public class Student extends Person{ //Weitere Attribute und Methoden } 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 13 Beispiel: Student extends Person // Klasse Person (Oberklasse): // Klasse Student (Unterklasse) public class Person { public class Student extends Person { private String name; private String vorname; private int matrikelnr; //Konstruktor public Person(String name, String vorname) { this.name = name; this.vorname = vorname; } // Konstruktor public Student(String name, String vorname, int matrikelnr){ super(name,vorname); this.matrikelnr = matrikelnr; } // Getter und Setter public String getName() { return name; } public void setName(String name) { this.name = name; } public String getVorname() { return vorname; } public void setVorname(String vorname) { this.vorname = vorname; } } // Getter und Setter public int getMatrikelnr() { return matrikelnr; } public void setMatrikelnr(int matrikelnr) { this.matrikelnr = matrikelnr; } 17.12.2015 } Javakurs 09: Mehr zur OO - Lorenz Schauer 14 Vererbung: Ein paar Regeln! Der Zugriff auf Instanzvariablen der Oberklasse: Direkter Zugriff über das Schlüsselwort super Bsp.: super.InstanzVaraibleOberklasse Nur möglich, wenn InstanzVaraibleOberklasse public oder protected deklariert wurde Private Instanzvariablen sind zwar vorhanden aber nicht sichtbar => Zugriff nur über Methoden möglich Private Methoden der Oberklasse werden nicht vererbt! Konstruktoren werden nicht vererbt! Der Konstruktor der Oberklasse kann jedoch im Konstruktor der Unterklasse mit super aufgerufen werden! super(); // Konstruktor der Oberklasse ohne Parameter super(typ param1, typ param2,….) // Konstruktor der Oberklasse mit Parameter Dieser Aufruf muss als erstes im Unterklassenkonstruktor definiert sein! 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 15 Verwendung der Klassen Wir haben nun die beiden Klassen Person und Student definiert, wobei: Student von Person erbt Student ist also auch immer eine Person, aber nicht jede Person ist ein Student D.h.: Wir können den Studenten auch als eine Person im Code betrachten und dementsprechend benutzen (Subtyping) Die Unterklasse ist ein Subtyp der Oberklasse Andersrum ist das nicht möglich! // Beispiel: Benutzung der Klassen Student studi1 = new Student("Matthias","Maier",9951); Person person1 = new Student("Hansi","Hinterseer",1234); //studi1 bietet alle Methoden eines Studenten: String name1 = studi1.getName(); int matnr1 = studi1.getMatrikelnr(); //person1 bietet bisher nur die Methoden einer Person! int matnr2 = person1.getMatrikelnr(); FEHLER: The method getMatrikelnr() is undefined for the type Person 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 16 Typkonvertierung Wir wissen jedoch, dass die Person person1 eigtl. auch ein Student ist und alle Informationen eines Studenten besitzt. In so einem Fall, können wir die Person person1 typkonvertieren, so dass daraus ein Student wird: Bsp.: Student neuer_student = (Student) person1; Bei der Typkonvertierung (type cast) wird überprüft, ob die tatsächliche Klasse von person1 eine Unterklasse von Person darstellt. Wenn ja: dann kein Problem Wenn nein: dann Laufzeitfehler: ClassCastException Mit dem Schlüsselwort instanceof lässt sich überprüfen, ob das Objekt tatsächlich eine Instanz der angefragten Klasse ist Beispiel: if(person1 instanceof Student){ // liefert true, falls person1 tatsächlich vom Typ Student ist System.out.println("Passt"); } 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 17 Die Klasse Object Implizit erben alle Klassen in Java von der Klasse Object Dadurch werden implizit bereits einige Methoden dieser Oberklasse angeboten Beispiele: String toString(); // in einen String konvertieren boolean equals(Object other); // auf Gleichheit testen Object clone(); // Kopie des Objektes anlegen Dies kann man auch sehen, wenn man in einer eigenen Klasse bspw. im Konstruktor this. eingibt und sich von Eclipse die Attribute und Methoden anzeigen lässt (Strg+Leertaste) 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 18 Programmieraufgabe zur Vererbung Legen Sie ein neues Eclipse-Projekt „Uebung09“ an und bearbeiten Sie darin folgende Aufgabe zur Vererbung in Java: Der Weihnachtsmann braucht für seine Fahrt auf dem Schlitten insgesamt 4 Rentiere, damit er vorwärts kommt. Da es aber im Wald dunkel ist, muss ein Rentier „Rudolph“ sein, der eine leuchtende Nase hat. Schreiben Sie eine Klasse „Weihnachtsmann“ mit folgenden Eigenschaften: Besitzt unveränderbaren Namen „Santa“ Besitzt eine private Liste vom Typ „Rentier“, welche die Rentiere speichert, die am Schlitten angebunden sind Außerdem besitzt er eine Methode, um Rentiere hinzuzufügen und eine Methode, um Rentiere zu entfernen Die Klasse hat noch eine Getter-Methode für die Rentierliste Außerdem gibt es eine Methode void losfahren(), damit der Weihnachtsmann losfahren kann. Die Methode gibt aber erst „Santa faehrt los “ aus, wenn mindestens 3 normale Rentiere und ein „Rudolph“ Rentier am Schlitten angebunden sind. Ist das nicht der Fall, passiert beim Aufruf der Methode nichts. 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 19 Programmieraufgabe zur Vererbung Implementieren Sie eine Klasse Rentier mit folgenden Eigenschaften: Jedes Rentier bekommt beim Erzeugen eine eindeutige ID (int), die nach der Erzeugung nicht mehr veränderbar ist! Außerdem hat jedes Rentier eine Größe (double), welche beim Erzeugen ebenfalls angegeben werden soll! Als Methoden stellt ein Rentier die beiden Getter seiner Instanzvariablen zur Verfügung, nämlich für int id und double groesse Implementieren Sie nun eine Klasse RentierRudolph, welche logischerweise auch ein Rentier ist (erbt von der Klasse Rentier) Rudolph hat den festen Namen „Rudolph“ und einen boolschen Wert leuchten, der angibt, ob er gerade leuchtet Die Klasse soll über 2 Methoden void leuchten() und void nichtLeuchten() den booleschen Wert entsprechend setzen können. Schreiben Sie nun eine Anwendung und erzeugen Sie sich einen Weihnachtsmann, der verschiedene Rentiere hinzufügt. Versuchen Sie dessen Methode losfahren() auszuführen. Zur Erinnerung: diese Methode sollte nur „Santa faehrt los“ ausgeben, wenn mindestens 3 normale Rentiere und ein „Rudolph“ am Schlitten angebunden sind. 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 20 Frohe Weihnachten in Java Ein kleines Java Beispiel um zu sagen: Frohe Weihnachten und an guadn Rutsch ins neue Jahr! 17.12.2015 Javakurs 09: Mehr zur OO - Lorenz Schauer 21