Objektorientierte Programmierung – Aufgaben & Lösungen

1. Grundsätze der objektorientierten Programmierung

Tipp: Überlege zuerst, was „Objekte“ im Alltag sind (Auto, Konto, Handy) und wie man sie mit Daten + Verhalten beschreiben könnte.

Lösung einblenden

Vier Grundprinzipien:

Kapselung:
Attribute einer Klasse werden vor direktem Zugriff geschützt (z. B. mit private). Zugriff nur über öffentliche Methoden (Getter/Setter). Dadurch kann man kontrollieren, welche Werte erlaubt sind.

Alltagsbeispiel:
Beim Auto kannst du nicht direkt am Motor drehen; du nutzt Gas- und Bremspedal, Tacho usw. – der Motor ist „gekapselt“.

2. Objektorientierte Modellierung – Von der Realität zur Klasse

Tipp: Denk daran: jede Klassenkarte beschreibt „Welche Daten hat das Ding?“ (Attribute) und „Was kann es tun?“ (Methoden). Koordinaten sind z. B. x und y in einem Raum.

Erstelle für ein Computerspiel Klassenkarten für Möbel, Geräte und Spielsachen. Erstelle eine Objektkarte für ein konkretes Objekt. Generalisiere die drei Klassen in eine Oberklasse „Spielobjekt“.

Lösung einblenden

Klassendiagramm (mit Koordinaten, 3 Attributen, Getter/Setter, Interaktionsmethode – aber ohne Vererbung):

@startuml
skinparam classAttributeIconSize 0
skinparam classAttributeIconColor Black

class Möbel {
  -x : int
  -y : int
  -farbe : String
  -material : String
  -hoeheCm : int
  +setPosition(x:int, y:int)
  +getPosition() : String
  +benutzen()
}

class Gerät {
  -x : int
  -y : int
  -name : String
  -stromverbrauchWatt : int
  -istAn : boolean
  +setPosition(x:int, y:int)
  +einschalten()
  +ausschalten()
}

class Spielsache {
  -x : int
  -y : int
  -name : String
  -farbe : String
  -level : int
  +setPosition(x:int, y:int)
  +interagiere()
}
@enduml

Objektkarte (PlantUML-Objektdiagramm):

@startuml
skinparam classAttributeIconSize 0
skinparam classAttributeIconColor Black

object "schrank1:Möbel" {
  x = 2
  y = 1
  farbe = "weiß"
  material = "Holz"
  hoeheCm = 200
}
@enduml

Hinweis: Normalerweise würde man jetzt die gemeinsame Struktur (z. B. x/y, Position) in einer Oberklasse Spielobjekt zusammenfassen. Hier lassen wir die eigentliche Vererbung aber bewusst weg.

3. Mit Objekten arbeiten

Tipp: Lies den Konstruktor wie eine Funktionssignatur. Die Reihenfolge der Parameter beim Erzeugen des Objekts muss genau zur Signatur passen.

Lösung einblenden

// Konstruktor: Auto(String farbe, String marke, int baujahr, int ps, int tankstand)
Auto a = new Auto("rot", "BMW", 2018, 150, 40);

// Beispiel-Haus mit (anzahlStockwerke, hatKeller, hausAdresse)
Haus h = new Haus(3, true, "Musterstraße 10");

4. Methoden mit Parametern ausführen

Tipp: Frag dich bei jedem Parameter: „Was bedeutet diese Information in der Realität?“ – liter beim Tanken, Anzahl Stockwerke beim Hausbau usw.

Lösung einblenden

Methode tanken(int liter) aufrufen:


    //in der Klasse selbst
this.tanken(20); //geht auch ohne this
    //in andere Klasse (an Objekt)
meinAuto.tanken(20);   // erhöht den Tankstand um 20 Liter

Datentypen:

Methode baueHaus aufrufen:


// Signatur: baueHaus(int anzahlStockwerke, boolean hatKeller, String hausAdresse)
arbeiter.baueHaus(3, false, "Waldweg 7");
// oder
this.baueHaus(3,false,"Waldweg 7");

Reihenfolge der Parameter:
Erst wird die Struktur des Hauses beschrieben (Stockwerke), dann eine wichtige Eigenschaft (Keller ja/nein) und am Ende die Adresse. Diese Reihenfolge ist logisch und leicht zu merken.

5. Konzept der Kapselung

Tipp: Stell dir vor, jemand könnte direkt jede Variable ändern – was könnte dabei alles schiefgehen? Genau das soll Kapselung verhindern.

Lösung einblenden

public int getTankstand() {
    return tankstand;
}

public void setTankstand(int value) {
    if (value >= 0) {        // Sicherstellen, dass der Wert sinnvoll ist
        this.tankstand = value;
    }
    // sonst: ignorieren oder Fehler werfen
}

Durch private-Attribute und Getter/Setter wird verhindert, dass der Tankstand z. B. auf einen negativen Wert gesetzt wird.

6. Methoden verändern und erstellen

Tipp: Überleg dir eine Methode, die etwas berechnet (z. B. Verbrauch in Litern) und gib dieses Ergebnis zurück – eine andere Methode oder Klasse kann dieses Ergebnis dann als Parameter weiterverwenden.

Lösung einblenden

Methode fahren(int kilometer), die move(int steps) nutzt:


public void fahren(int kilometer) {
    move(kilometer);            // vorhandene Methode, die die Position ändert
    tankstand -= kilometer * 0.05;  // 5% des Werts als Verbrauch
}

Diskussion Rückgabewert:

7. Eine Klasse erstellen

Tipp: Starte bei der Klassenkarte: erst alle Attribute sammeln, dann Konstruktor bauen, dann Methoden ergänzen. Der Code ist nur die „Übersetzung“ der Karte in Java.

Erstelle die Klasse Auto mit den Attributen farbe, marke, baujahr, ps, tankstand. Schreibe zwei Methodenköpfe für schalte(). Gib den Methodenkopf von anzahlAutos() an. Erkläre den Weg von der Klassenkarte zur fertigen Klasse. Die Klasse Auto soll von der Klasse Fahrzeug erben.

Lösung einblenden

Ausimplementierte Klasse Auto (mehr als gefordert, aber korrekt):


public class Auto {

    // Attribute aus der Aufgabenstellung
    private String farbe;
    private String marke;
    private int baujahr;
    private int ps;
    private int tankstand;

    // Klassenattribut, zählt alle erstellten Autos
    private static int zaehler = 0;

    // Konstruktor: alle Attribute werden initialisiert
    public Auto(String farbe, String marke, int baujahr, int ps, int tankstand) {
        this.farbe = farbe;
        this.marke = marke;
        this.baujahr = baujahr;
        this.ps = ps;
        this.tankstand = tankstand;
        zaehler++;
    }

    // Methodenköpfe für schalte():
    public void schalte() {
        // einfache Version ohne Parameter
    }

    public void schalte(String modus) {
        // Überladung mit einem Parameter, z.B. "Sport", "Eco"
    }

    // Geforderter Methodenkopf der statischen Methode:
    public static int anzahlAutos() {
        return zaehler;
    }
}

UML Auto (mit Sichtbarkeitssymbolen):

@startuml
skinparam classAttributeIconSize 0
skinparam classAttributeIconColor Black

class Auto {
  -farbe : String
  -marke : String
  -baujahr : int
  -ps : int
  -tankstand : int
  +schalte()
  +schalte(modus : String)
  +anzahlAutos() : int
}
@enduml

Wie komme ich von der Klassenkarte zur fertigen Klasse?

  1. Alle Attribute aus der Klassenkarte übernehmen und in Java als private Felder anlegen.
  2. Einen Konstruktor schreiben, der für jedes Attribut einen Parameter hat und diese mit this.attribut = parameter; setzt.
  3. Die in der Klassenkarte notierten Methoden als Methodenköpfe anlegen (Rückgabewert, Name, Parameter).
  4. Falls es eine statische Information gibt (z. B. „Anzahl aller Autos“), ein static-Attribut + passende static-Methode ergänzen.
  5. Optional: Getter/Setter für die Attribute hinzufügen, um Kapselung umzusetzen.