SemaTrain Logo Ein Fachportal von SemaTrain

Fortgeschrittene Objektorientierung

Sie vertiefen Vererbung, Interfaces und Abstraktion – und lernen, Architektur-Entscheidungen sauber zu begründen (kursnah im SemaTrain-Kontext).

Hinweis: Codebeispiele nutzen Beispieldaten; Fokus liegt auf Struktur/Design.

Java Fortgeschrittenen Schulung – Kursbezug

Dieses Kapitel ist Teil des Lernpfads zur Java Fortgeschrittenen Schulung. Fokus: Design-Entscheidungen (Interface vs. Vererbung vs. Komposition) nachvollziehbar treffen.

Ziel dieses Kapitels: Sie bauen OOP-Strukturen, die erweiterbar sind (neue Varianten ohne Umbau) und können Ihre Wahl (Abstraktion, Interface, Vererbung) begründen.

Worum geht’s?

Lehr-/Lernziele

Nach diesem Kapitel können Sie …

Interface als Vertrag (stabil, austauschbar)

Ideal, wenn mehrere Implementierungen möglich sind (z.B. Rabattregeln, Ausgabeformate, Versandarten).

Interface: Preisregel als austauschbare Strategie (SemaTrain-Kontext) (Java)
public interface Preisregel {
  double anwenden(double grundpreis);
}

public class KeinRabatt implements Preisregel {
  public double anwenden(double grundpreis) { return grundpreis; }
}

public class OnlineRabatt10 implements Preisregel {
  public double anwenden(double grundpreis) { return grundpreis * 0.90; }
}

Abstrakte Klasse für gemeinsamen Code

Wenn mehrere Schulungsarten gemeinsame Felder/Logik haben, aber Details variieren, passt eine abstrakte Basis.

Abstrakte Klasse: gemeinsamer Kern + variierende Details (IT-Training) (Java)
public abstract class Schulung {
  protected final String titel;
  protected final int tage;
  protected final double grundpreis;

  protected Schulung(String titel, int tage, double grundpreis) {
    this.titel = titel;
    this.tage = tage;
    this.grundpreis = grundpreis;
  }

  public abstract String ortLabel();

  public String zusammenfassung() {
    return titel + " | " + tage + " Tage | Ort: " + ortLabel();
  }
}

public class OnlineSchulung extends Schulung {
  public OnlineSchulung(String titel, int tage, double grundpreis) {
    super(titel, tage, grundpreis);
  }
  public String ortLabel() { return "online"; }
}

public class PraesenzSchulung extends Schulung {
  private final String stadt;

  public PraesenzSchulung(String titel, int tage, double grundpreis, String stadt) {
    super(titel, tage, grundpreis);
    this.stadt = stadt;
  }
  public String ortLabel() { return stadt; }
}

Polymorphie: gleiche API, verschiedene Umsetzung

Der Aufrufer arbeitet gegen den Vertrag (Interface/abstrakte Klasse) – Implementierung ist austauschbar.

Polymorphie: gleiche Nutzung, unterschiedliche Ausprägungen (Java)
public class Demo {
  public static void main(String[] args) {

    Schulung s1 = new OnlineSchulung("Java Fortgeschritten (SemaTrain)", 5, 2082.50);
    Schulung s2 = new PraesenzSchulung("Java Fortgeschritten (SemaTrain)", 5, 2082.50, "Hamburg");

    System.out.println(s1.zusammenfassung());
    System.out.println(s2.zusammenfassung());
  }
}

Komposition statt Vererbung (Standardwahl)

Wenn eine Schulung etwas „hat“ (z.B. Preisregel, Validator, Logger), ist Komposition meist besser als Vererbung.

Komposition: Service + austauschbare Regel (Java)
public class BuchungsService {
  private final Preisregel preisregel;

  public BuchungsService(Preisregel preisregel) {
    this.preisregel = preisregel;
  }

  public double endpreis(double grundpreis) {
    return preisregel.anwenden(grundpreis);
  }
}

public class Anwendungsfall {
  public static void main(String[] args) {

    BuchungsService online = new BuchungsService(new OnlineRabatt10());
    BuchungsService praesenz = new BuchungsService(new KeinRabatt());

    System.out.println("Online-Endpreis: " + online.endpreis(2082.50));
    System.out.println("Praesenz-Endpreis: " + praesenz.endpreis(2082.50));
  }
}

Praxisaufgabe (Mini)

Beitrag zu den Lehr-/Lernzielen: LZ1 (Interface) · LZ2 (Polymorphie) · LZ3 (Komposition)

  1. Erstellen Sie ein Interface NachrichtenFormatierer mit String formatieren(String text).
  2. Implementieren Sie zwei Varianten: KlartextFormatierer und GrossbuchstabenFormatierer.
  3. Bauen Sie einen BenachrichtigungsService, der einen Formatierer per Konstruktor bekommt (Komposition).
  4. Geben Sie 2 Nachrichten aus – einmal klar, einmal in Großbuchstaben.
Lösung anzeigen
Lösung: Interface + Komposition + Polymorphie (SemaTrain-Kontext) (Java)
public interface NachrichtenFormatierer {
  String formatieren(String text);
}

public class KlartextFormatierer implements NachrichtenFormatierer {
  public String formatieren(String text) { return text; }
}

public class GrossbuchstabenFormatierer implements NachrichtenFormatierer {
  public String formatieren(String text) { return text.toUpperCase(); }
}

public class BenachrichtigungsService {
  private final NachrichtenFormatierer formatierer;

  public BenachrichtigungsService(NachrichtenFormatierer formatierer) {
    this.formatierer = formatierer;
  }

  public void senden(String nachricht) {
    System.out.println(formatierer.formatieren(nachricht));
  }
}

public class DemoPraxis {
  public static void main(String[] args) {
    BenachrichtigungsService klar = new BenachrichtigungsService(new KlartextFormatierer());
    BenachrichtigungsService gross = new BenachrichtigungsService(new GrossbuchstabenFormatierer());

    klar.senden("Kurs: Java Fortgeschritten (SemaTrain) | Ort: online");
    gross.senden("Hinweis: Bitte Technik-Check durchführen");
  }
}
Optional: typische Stolperfallen
  • Vererbung für „has-a“: Service/Regel als Feld (Komposition), nicht als Basisklasse.
  • Zu breite Basisklassen: Abstrakte Klasse nur für echten gemeinsamen Kern.
  • Zu viele Mini-Interfaces: lieber wenige, klare Verträge als „Interface-Explosion“ ohne Nutzen.

Kurz-Takeaways

Quiz: Fortgeschrittene Objektorientierung (Lehr-/Lernziele Check)

1. (LZ1) Wann ist ein Interface meist die bessere Wahl als Vererbung?

2. (LZ2) Was beschreibt Polymorphie am treffendsten?

3. (LZ3) Was ist ein gutes Signal für „Komposition statt Vererbung“?

4. (LZ1) Welche Aussage zur abstrakten Klasse stimmt?

Praxisaufgabe

Mini-Projekt: „SemaTrain Training-Engine“ (OOP-Design im Kurskontext)

Beitrag zu den Lehr-/Lernzielen: LZ1 (Abstraktion/Interface) · LZ2 (Polymorphie) · LZ3 (Komposition)

Sie modellieren Trainingsangebote (Online/Präsenz) und berechnen Preise über austauschbare Regeln – wie in einer kleinen SemaTrain-internen „Buchungslogik“ für IT-Trainings.

Lösung anzeigen
Lösung: SemaTrain Training-Engine (Abstraktion + Polymorphie + Komposition) (Java)
public interface Preisregel {
  double anwenden(double grundpreis);
}

public class OnlineRabatt10 implements Preisregel {
  public double anwenden(double grundpreis) { return grundpreis * 0.90; }
}

public class KeinRabatt implements Preisregel {
  public double anwenden(double grundpreis) { return grundpreis; }
}

public abstract class Schulung {
  protected final String titel;
  protected final int tage;
  protected final double grundpreis;

  protected Schulung(String titel, int tage, double grundpreis) {
    this.titel = titel;
    this.tage = tage;
    this.grundpreis = grundpreis;
  }

  public abstract String ortLabel();

  public String zusammenfassung() {
    return titel + " | " + tage + " Tage | Ort: " + ortLabel();
  }
}

public class OnlineSchulung extends Schulung {
  public OnlineSchulung(String titel, int tage, double grundpreis) { super(titel, tage, grundpreis); }
  public String ortLabel() { return "online"; }
}

public class PraesenzSchulung extends Schulung {
  private final String stadt;

  public PraesenzSchulung(String titel, int tage, double grundpreis, String stadt) {
    super(titel, tage, grundpreis);
    this.stadt = stadt;
  }
  public String ortLabel() { return stadt; }
}

public class BuchungsService {
  private final Preisregel preisregel;

  public BuchungsService(Preisregel preisregel) {
    this.preisregel = preisregel;
  }

  public double endpreis(Schulung schulung) {
    return preisregel.anwenden(schulung.grundpreis);
  }
}

public class DemoProjekt {
  public static void main(String[] args) {

    Schulung online = new OnlineSchulung("Java Fortgeschritten (SemaTrain)", 5, 2082.50);
    Schulung praesenz = new PraesenzSchulung("Java Fortgeschritten (SemaTrain)", 5, 2082.50, "Hamburg");

    BuchungsService onlineBuchung = new BuchungsService(new OnlineRabatt10());
    BuchungsService praesenzBuchung = new BuchungsService(new KeinRabatt());

    System.out.println(online.zusammenfassung());
    System.out.println("Endpreis (Online): " + onlineBuchung.endpreis(online));

    System.out.println(praesenz.zusammenfassung());
    System.out.println("Endpreis (Praesenz): " + praesenzBuchung.endpreis(praesenz));
  }
}