6th Java Lesson (Java Course @ TUD)

https://github.com/Trivo25/tud-java-course

November 25, 2021

Während Ihr darauf wartet, dass es beginnt..

Java

Objektorientierte Programmierung

Florian Kluge, Moritz Schulz

  1. November 2021


Florian.Kluge@mailbox.tu-dresden.de

Moritz.Schulz2@mailbox.tu-dresden.de

Was wir heute machen

Festigung der Grundlagen der Objektorientierten Programmierung

  1. Wiederholung
  2. Programme betrachten
  3. Aufgabe zur Anwendung

Contact

Florian Kluge

Florian.Kluge@mailbox.tu-dresden.de

Moritz Schulz

Moritz.Schulz2@mailbox.tu-dresden.de

Kurze Info zum Kurs

  • bitte abmelden / entschuldigen, wenn ihr nicht kommt
    • zwei Mal in Folge unentschuldigt fehlen => ausgetragen
  • praktische Aufgaben- und Beispiel-basierte Lernweise
    • wir laufen herum und gucken, dass ihr zurecht kommt
  • bitte, fragt gern, jederzeit
    • auch per E-Mail / via Kursseite
  • uns geht es darum, alle mitzunehmen

Stay up to date

  • die E-Mails der TUD regelmäßig überprüfen
    • z.B. Bekanntgabe der Veröffentlichung der Folien
      • auf der Seite des Programmierkurses

Los geht’s!

Wiederholung

  • Klassen sind Vorlagen
  • aus Klassen können Objekte erstellt werden
  • Objekte haben
    • Eigenschaften (Attribute - Variablen eines Objekts)
    • Funktionalität (Methoden - “Funktionen” eines Objekts)
  • Konstruktoren tragen den Namen der Klasse
    • public Klassenname( /* Parameter */ ) { /* ... */ }
  • Objekte werden mit new erstellt
    • z.B. Hund laika = new Hund(12, "Laika");
    • in den Klammern stehen die Parameter für den Konstruktor
  • Klassen bilden einen Scope

Beispielprogramm 1

public class Programm {
    public static void main(String[] args) {
        Quadrat luca = new Quadrat(10.0f);
        float flaeche = luca.flaeche();
    }
}

class Quadrat {
    public float seitenlaenge;
    
    public Quadrat(float a){
        seitenlaenge = a;
    }

    public float flaeche() {
        return seitenlaenge * seitenlaenge;    
    }
}

Beispielprogramm 1: Fragen

  • Was ist luca?
  • Welcher Bereich des Programms kennt luca?
  • Welcher Bereich des Programms kennt seitenlaenge?
  • Welcher Bereich des Programms kennt a?
  • Welchen Wert hat flaeche in main(String[] args)?

Beispielprogramm 2

Wo liegt der Fehler?

public class Programm1 {
    public static void main(String[] args) {
        Auto auto1 = new Auto();
        System.out.println(auto1.farbe);
    }
}

class Auto {
    public String farbe;
    public Auto(String autoFarbe) {
        farbe = autoFarbe;
    }
}

Beispielprogramm 2: Lösung

public class Programm1 {
    public static void main(String[] args) {
        Auto auto1 = new Auto("rot"); // <- Hier hat der Parameter gefehlt
        System.out.println(auto1.farbe);
    }
}

class Auto {
    public String farbe;
    public Auto(String autoFarbe) {
        farbe = autoFarbe;
    }
}

Beispielprogramm 3

Was haben auto1 und auto2 gemeinsam?

public class Programm2 {
    public static void main(String[] args) {
        Auto auto1 = new Auto(7, 1996, "rot");
        Auto auto2 = new Auto(7, 2014, "rot");
    }
}

class Auto {
    public int sitzplaetze;
    public int baujahr;
    public String farbe;
    
    public Auto(int autoSitzplaetze, int autoBaujahr, String autoFarbe) {
        sitzplaetze = autoSitzplaetze;
        baujahr = autoBaujahr;
        farbe = autoFarbe;
    }
    
    public static void beschreibe() {
        System.out.println("Dieses Auto ist " + farbe);
    }
}

Beispielprogramm 3: Lösung

  • beides Objekte der Klasse Auto
    • d.h. beide haben die gleichen Attribute und Methoden
  • gleicher Attributwert bei sitzplaetze und farbe
  • verschiedene Attributwerte bei baujahr
Aufgabe der letzten Stunde

Modelliert einen Würfel als Klasse.

Würfel haben folgende Attribute:

  • Seitenlänge

Würfel haben folgende Methoden:

  • eine, die das Volumen berechnet
  • eine, die den Oberflächeninhalt berechnet
  • halbiereSeitenlängen() ändert Seitenlänge auf die Hälfte

Schreibt ein Programm, das ein Objekt vom Typ Würfel erstellt. Es soll ausgeben, welches Volumen und welcher Flächeninhalt vom Würfel-Objekt berechnet wird.

Beispiellösung zur Aufgabe der letzten Stunde
public class Programm {
    public static void main(String[] args) {
        float a = 7;
        Würfel wuerfel1 = new Würfel(a);
        wuerfel1.halbiereSeitenlängen();
        
        System.out.println("Volumen: " + wuerfel1.Volumen());
        System.out.println("Oberflächeninhalt: " + wuerfel1.Oberflacheninhalt());
    }
}

class Würfel {
    public float Seitenlänge;
    public Würfel(float a){
        Seitenlänge = a;
    }

    public float Volumen() {
        return Seitenlänge*Seitenlänge*Seitenlänge;    
    }
    public float Oberflacheninhalt() {
        return 6*(Seitenlänge*Seitenlänge);
    }
    public void halbiereSeitenlängen() {
        Seitenlänge = Seitenlänge / 2;
    }

}
Beispiellösung zur Aufgabe der letzten Stunde - Fragen Teil 1
  1. Welche Attribute hat ein Würfel?
  2. Welche Methoden hat ein Würfel?
  3. Wie viele Objekte werden in dem Programm erstellt? Wie heißen sie?
  4. Was ist der Unterschied zwischen void und float bei den Methoden?
  5. Kann return auch weglassen werden?
  6. Wie viele Parameter fordert der Konstruktor von Würfel?
  7. Könnte ich den Konstruktor anders nennen?
  8. Was, wenn ich in main(String[] args) den float nicht a, sondern b nennen würde?
  9. Könnte ich auch public class Würfel schreiben?
Beispiellösung zur Aufgabe der letzten Stunde - Antworten Teil 1
  1. public float Seitenlänge (Z. 13)
  2. public float Volumen(), public float Oberflacheninhalt(), public void halbiereSeitenlängen() (Z. 18, 21, 24)
  3. ein Objekt Würfel wuerfel1 (Z. 4)
  4. bei Methoden: void heißt, kein Wert wird zurückgegeben. float heißt, kein Wert wird zurückgegeben
  5. Nein, wenn der Methodenrückgabetyp nicht void ist, ist ein return erforderlich
  6. einen: float a (Z. 14)
  7. Nur, wenn ich auch die Klasse umbenenne
  8. Wenn ich a in b auf Zeilen 3 und 4 ändere, funktioniert das. Der Scope von main(String[] args) hängt nicht mit dem der Klasse Würfel zusammen
  9. Nein, denn pro .java-Datei kann es nur eine public class geben
Beispiellösung zur Aufgabe der letzten Stunde - Fragen Teil 2
  1. Kann ich einen neuen Würfel mit einer anderen Seitenlänge erstellen?
  2. Was, wenn ich im Konstruktor a = Seitenlänge; schreibe?
  3. Kann ich die Klasse Würfel auch, einfach so, in die Klasse Programm verschieben?
  4. Was passiert, wenn ich public float Seitenlänge; von der Klasse Würfel in die Klasse Programm verschiebe?
  5. Was passiert, wenn ich die Methode public void halbiereSeitenlängen() von der Klasse Würfel in die Klasse Programm verschiebe?
Beispiellösung zur Aufgabe der letzten Stunde - Antworten Teil 2
  1. Ja, klar. Dafür sind Klassen und Objekte da.
  2. Dann bleibt das Attribut Seitenlänge im Würfel auf dem Standardwert 0
  3. Nein, einfach so geht das nicht.
  4. Dann werden Fehlermeldungen wegen der Zeilen 15, 19, 22, 25 entstehen, denn der Scope der Klassen Würfel und Programm überschneiden sich nicht. Das heißt, dass Seitenlänge innerhalb der Klasse Würfel nicht bekannt wäre.
  5. Dann würde zum Einen in public void halbiereSeitenlängen() eine Fehlermeldung entstehen, weil die Variable Seitenlängen in der Klasse Programm nicht bekannt ist. Zum Anderen würde auf Zeile 5 ein Fehler entstehen, weil die Methode halbiereSeitenlängen() dann nicht für Objekte der Klasse Würfel definitiert wäre
Frage zu Objekten und Scopes

Was gibt das Programm aus?

public class Demonstration {
    public static void main(String[] args) {
        int hoehe = 393;
        Hochhaus hh = new Hochhaus(3000);
        System.out.println(hoehe);
        hoehe = hh.hoehe;
        System.out.println(hoehe);
    }
}

class Hochhaus {
    public int hoehe;
    public Hochhaus(int hoehe) {
        hoehe = hoehe;
        System.out.println("Die Höhe ist: " + hoehe);
    }
}
Frage zu Objekten und Scopes

Ausgabe:

Die Höhe ist: 3000
393
0

Wieso?

Frage zu Objekten und Scopes: Erklärung

Die hoehe von hh bleibt 0. Denn auf Zeile 14 wird beide Male die Höhe von Zeile 13 gemeint.

Wie können wir das Problem beheben?

Frage zu Objekten und Scopes: Lösungsidee 1

Parameter vom Konstruktor umbenennen

class Hochhaus {
    public int hoehe;
    public Hochhaus(int hoeheH) {
        hoehe = hoeheH;
        System.out.println("Die Höhe ist: " + hoehe);
    }
}
Frage zu Objekten und Scopes: Lösungsidee 2
  • alternativ this. verwenden.
  • this ist das aktuelle Objekt.
  • müsst ihr nicht beherrschen
public class Demonstration {
    public static void main(String[] args) {
        int hoehe = 393;
        Hochhaus hh = new Hochhaus(3000);
        System.out.println(hoehe);
        hoehe = hh.hoehe;
        System.out.println(hoehe);
    }
}

class Hochhaus {
    public int hoehe; // <-- diese ist mit this.hoehe gemeint
    public Hochhaus(int hoehe) {
        this.hoehe = hoehe; // nur hier eine Änderung
        System.out.println("Die Höhe ist: " + hoehe);
    }
}

Modifiers

public, private, protected, static, final, ..

public und private Modifier

  • public und private bestimmen von wo wir auf die Attribute und Methoden einer Klasse zugreiffen können
    • also öffentlich (public) oder nur privat (auch intern) (private)
  • protected (Standardwert) klären wir später

private Modifier

  • auf Attribute und Methoden welche mit private gekennzeichnet sind können wir nur innerhalb der Klasse zugreifen
class Auto {
    private String farbe;
    
    public void printColor() {
        // hier haben wir zugriff auf farbe
        System.out.println(farbe);
    }
}

// ...
public class Programm {
    public static void main(String[] args) {
        Auto auto1 = new Auto();
        // hier haben wir auf farbe keinen Zugriff!
        System.out.println(auto1.farbe); //geht nicht
        auto1.farbe = "türkis"; //geht nicht
    }
}

private im Vergleich zu public

  • public erlaubt uns auf Attribute und Methoden außerhalb der Klasse zuzugreifen
class Auto {
    public String farbe; // ist nun public!
}

// ...
public class Programm {
    public static void main(String[] args) {
        Auto auto1 = new Auto();
        // hier haben wir _direkten_ Zugriff auf auto1.farbe
        System.out.println(auto1.farbe);
        auto1.farbe = "türkis";
    }
}

trotzdem private Attribute lesen und verändern

  • wenn (also Variablen oder Funktionen) privat sind, können wir auf diese nicht direkt von außen zugreifen
  • es gibt einen Umweg - indirekter Zugriff:
    • mit der Hilfe von sogenannten getter und setter-Methoden
    • getter sind wie ein ‘Read-Only’-Mechanismus
class Auto {
    private String farbe;
    
    // getter-Methode für das Attribut farbe
    public String getFarbe() {
        return farbe;
    }
}

// ...
public class Privat {
    public static void main(String[] args) {
        Auto auto1 = new Auto();
        // hier haben wir _indirekten_ Zugriff auf die Farbe
        System.out.println(auto1.getFarbe());
    }
}

trotzdem private Attribute lesen und verändern

  • mit setter können wir private-Attribute ändern, mit der Hilfe von Funktionen
class Auto {
    private String farbe;
    
    // setter-Methode um die Farbe zu ändern
    public String setFarbe(String neueFarbe) {
        farbe = neueFarbe;
    }
}

// ...
public class Privat {
    public static void main(String[] args) {
        Auto auto1 = new Auto();
        // hier haben wir _indirekten_ Zugriff auf die Farbe
        auto1.setFarbe("blau");
    }
}

Wofür getter und setter?

  • mit getter haben wir einen ‘Read-Only’ Mechanismus
    • somit vermeiden wir, dass unser Programm willkürlich Attribute eines Objektes ändern kann
  • mit setter können wir kontrolliert Attribute ändern und setzen
    • um beispielsweise vorher die neue Variable zu überprüfen

⇒ sauberer Code und kontrollierte Zustände innerhalb eines Programms

Beispiel setter

class Auto {
    // durch setFarbe wird farbe nur unter bestimmten Bedingungen geändert
    private String farbe;
    
    public void setFarbe(String neueFarbe) {
        if(neueFarbe == "blau" || neueFarbe == "rot") {
            farbe = neueFarbe;
        } else {
            // tue nichts; Attribut farbe wird nicht geändert
        }
    }
}
final
  • Variablen können Konstanten sein
    • mit final deklariert und direkt belegt
    • final Attribute können also nachträglich nicht verändert werden!
    • Namen von Konstanten werden meist in GROẞBUCHSTABEN geschrieben
class Circle {
    private final float PI = 3.1415927; 
    private float radius;
    
    public Circle(float radius) {
        this.radius = radius;
    } 
    
    // ...
    
    public float berechneDurchmesser() {
        return 2 * PI * radius;
    }
}
Modifier-chaining
  • mehrere Modifier auf einmal sind zulässig
    • Beispiel: public static void main(String[] args){}
  • erst Modifier welche den Zugriff beschreiben (private, public, protected)
    • danach static und final
Bankkonto - mittel - Teil 1
  • schreibt eine Klasse Bankkonto welches folgende Attribute hat
    • String: kontoInhaber - Name Kontoinhaber*in
    • float: maxiUeberzug - Maximum welcher Betrag das Konto überzogen werden kann(‘im Minus’)
    • String: iban - IBAN/Kontoaddresse
    • int: anzahlTransaktionen
    • float: guthaben - Guthaben
Bankkonto - mittel - Teil 2
  • erweitert die Klasse Bankkonto um folgende Methoden (Parameter ausgelassen):
    • boolean: sendMoney() - schickt einen Betrag an ein anderes Konto und passt das Guthaben an, gibt false oder true zurück wenn es erfolgreich war oder nicht
    • void: payIn() - zahlt Geld in das Konto ein
    • boolean: withdraw() - hebt Geld von dem Konto ab, gibt false oder true zurück wenn es erfolgreich war oder nicht
Pokémon - schwer - Teil 1
  • Schreibt ein Pokémon-Spiel in dem sich zwei Pokemons gegenseitig attackieren!
  • Pokémons kämpfen (hier) gegeneinander, indem sie sich gegenseitig Lebenspunkte abziehen
  • Nutzt dafür eine Klasse Pokemon mit folgenden Attributen:
    • String: name - Name des Pokémons
    • private float: health - Lebenspunkte des Pokémons
    • private float: attackPower - Angriffspunkte des Pokémons
    • private boolean: isDead - boolean ob Pokémon am Leben ist oder nicht
Pokémon - schwer - Teil 2
  • Die Klasse Pokemon soll folgende Methoden haben (Parameter ausgelassen):
    • boolean: getIsDead() - gibt true oder false zurück wenn Pokémon lebt bzw. wenn nicht
    • void: attack() - nimmt ein Pokémon-Objekt als Methoden-Parameter und greift es an, fügt im attackPower Schaden zu!
    • void: dealDamage() - zieht Leben des Pokémons ab

Nächste Stunde

  • Weiterführend: objektorientierte Programmierung
    • Vererbung

See course materials here: https://trivo25.github.io/tud-java-course/

Check out the Cheat Sheet: http://tiny.cc/java-cs