Tipp: Überlege zuerst, was „Objekte“ im Alltag sind (Auto, Konto, Handy) und wie man sie mit Daten + Verhalten beschreiben könnte.
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“.
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“.
@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
@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.
Tipp: Lies den Konstruktor wie eine Funktionssignatur. Die Reihenfolge der Parameter beim Erzeugen des Objekts muss genau zur Signatur passen.
// 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");
Tipp: Frag dich bei jedem Parameter: „Was bedeutet diese Information in der Realität?“ – liter beim Tanken, Anzahl Stockwerke beim Hausbau usw.
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:
int → ganze Zahl (z. B. 5, -2, 100)boolean → wahr/falsch (true oder false)String → Text (z. B. "Musterstraße 10")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.
Tipp: Stell dir vor, jemand könnte direkt jede Variable ändern – was könnte dabei alles schiefgehen? Genau das soll Kapselung verhindern.
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.
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.
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:
int berechneReichweite()double berechneVerbrauch(int kilometer)
navigation.zeigeReichweite(auto.berechneReichweite()); // Rückgabewert als Parameter
void hupe()void druckeInfos()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.
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;
}
}
@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
private Felder anlegen.this.attribut = parameter; setzt.static-Attribut + passende static-Methode ergänzen.