Hoofdstuk 12 — Overerving en Polymorfisme (hergebruik via hiërarchieën)
In dit hoofdstuk leer je hoe klassen kunnen erven van elkaar (extends), hoe je gedrag overschrijft (override), en hoe polymorfisme werkt via een gemeenschappelijk basistype. We bespreken ook super, final, abstracte klassen en interfaces, en tonen moderne patronen zoals pattern matching met instanceof.
Voorbeeld 1 — Basis overerving en overriding
class Dier { void maakGeluid() { System.out.println("..."); } }
class Hond extends Dier { @Override void maakGeluid() { System.out.println("Woef"); } }
class Kat extends Dier { @Override void maakGeluid() { System.out.println("Miauw"); } }
public class Demo12_1 {
public static void main(String[] args) {
Dier d1 = new Hond();
Dier d2 = new Kat();
d1.maakGeluid();
d2.maakGeluid();
}
}
Voorbeeld 2 — Polymorfisme in een methode
class GeluidPrinter {
static void printGeluid(Dier d) { d.maakGeluid(); }
}
public class Demo12_2 {
public static void main(String[] args) {
GeluidPrinter.printGeluid(new Hond());
GeluidPrinter.printGeluid(new Kat());
}
}
Voorbeeld 3 — super gebruiken
class Vorm {
String naam;
Vorm(String naam) { this.naam = naam; }
String beschrijf() { return "Vorm: " + naam; }
}
class Cirkel extends Vorm {
double r;
Cirkel(double r) { super("Cirkel"); this.r = r; }
@Override String beschrijf() { return super.beschrijf() + ", r=" + r; }
}
public class Demo12_3 {
public static void main(String[] args) {
System.out.println(new Cirkel(2.5).beschrijf());
}
}
Voorbeeld 4 — final om override te voorkomen
class Basis { final void nietOverschrijven() { System.out.println("vast gedrag"); } }
class Afgeleid extends Basis { /* kan niet overriden */ }
Voorbeeld 5 — Abstracte klasse en concrete subklassen
abstract class Figuur {
abstract double oppervlakte();
}
class Rechthoek extends Figuur {
double b, h;
Rechthoek(double b, double h){ this.b = b; this.h = h; }
@Override double oppervlakte(){ return b * h; }
}
class Cirkel2 extends Figuur {
double r;
Cirkel2(double r){ this.r = r; }
@Override double oppervlakte(){ return Math.PI * r * r; }
}
public class Demo12_5 {
public static void main(String[] args) {
Figuur f = new Cirkel2(1);
System.out.println(f.oppervlakte());
}
}
Voorbeeld 6 — Interface en meerdere implementaties
interface Betaalbaar { void betaal(double bedrag); }
class KaartBetaling implements Betaalbaar { public void betaal(double bedrag){ System.out.println("Kaart: " + bedrag); } }
class ContantBetaling implements Betaalbaar { public void betaal(double bedrag){ System.out.println("Cash: " + bedrag); } }
public class Demo12_6 {
public static void main(String[] args) {
Betaalbaar b = new KaartBetaling();
b.betaal(12.50);
b = new ContantBetaling();
b.betaal(7.95);
}
}
Voorbeeld 7 — instanceof met pattern matching (moderne Java)
public class Demo12_7 {
static void beschrijf(Dier d) {
if (d instanceof Hond h) {
System.out.println("Hond gezien");
h.maakGeluid();
} else if (d instanceof Kat k) {
System.out.println("Kat gezien");
k.maakGeluid();
} else {
System.out.println("Onbekend dier");
}
}
public static void main(String[] args) {
beschrijf(new Hond());
beschrijf(new Kat());
}
}
Voorbeeld 8 — @Override annotatie helpt fouten voorkomen
class Basis2 { void doeIets() {} }
class Afleid2 extends Basis2 { @Override void doeIets() { System.out.println("ok"); } }
Tips:
- Gebruik overerving spaarzaam; prefereer samenstelling ("has-a") boven overerving ("is-a") wanneer passend.
- Markeer methoden/klassen
finalals je extensie wil beperken. - Gebruik interfaces voor contracten en losjes gekoppelde ontwerpen.
Koppeling met oefeningen:
- Zie
java-workbook/src/chapter_12.mdvoor opdrachten rond overerving, interfaces en polymorfisme. - Uitwerkingen in
java-solutions/src/chapter_12.mden bijbehorende Java-bestanden.