Inheritance: gedrag overnemen en uitbreiden¶
Doel¶
Je leert hoe inheritance (overerving) werkt en welk probleem het oplost. Inheritance maakt het mogelijk om bestaande classes uit te breiden met nieuw gedrag zonder alles opnieuw te schrijven.
1. Het probleem: herhaling tussen vergelijkbare classes¶
Stel dat je in p5.js twee soorten ballen hebt: gewone ballen en zwaartekrachtballen. Je eerste poging ziet er misschien zo uit:
// Een gewone bal
class Ball {
constructor(x, y, speed, color) {
this.x = x;
this.y = y;
this.speed = speed;
this.color = color;
}
move() {
this.x += this.speed;
}
show() {
fill(this.color);
circle(this.x, this.y, 20);
}
}
// Een bal met zwaartekracht
class GravityBall {
constructor(x, y, speed, color, gravity) {
this.x = x;
this.y = y;
this.speed = speed;
this.color = color;
this.gravity = gravity;
}
move() {
this.y += this.gravity; // extra gedrag
this.x += this.speed;
}
show() {
fill(this.color);
circle(this.x, this.y, 20);
}
}
Wat valt op? Beide classes hebben veel dezelfde code (x, y, speed, color, show()). Als je later iets aanpast in Ball, moet je het ook in GravityBall doen.
Denkvraag
Wat als je nog meer varianten wilt maken (bijv. stuiterballen, kleurveranderende ballen)? Hoe onderhoudbaar blijft dit?
2. De oplossing: overerving met extends¶
Inheritance laat een class voortbouwen op een andere class. Zo kun je alles van Ball hergebruiken en alleen de verschillen toevoegen.
class GravityBall extends Ball {
constructor(x, y, speed, color, gravity) {
super(x, y, speed, color); // roept de constructor van Ball aan
this.gravity = gravity;
}
move() {
this.y += this.gravity; // nieuw gedrag
super.move(); // gebruik ook de move() van Ball
}
}
Hier:
extends Ballbetekent datGravityBallalles vanBallerft.super()roept de constructor vanBallaan om de basiswaarden in te stellen.super.move()gebruikt de oorspronkelijke functie uit de parent class.
Mini-opdracht:
- Maak een
GravityBalldie langzaam naar beneden valt Γ©n horizontaal beweegt. - Pas de
gravityaan om het verschil te zien.
3. Voorbeeld in actie¶
let balls = [];
function setup() {
createCanvas(400, 200);
balls.push(new Ball(50, 100, 2, 'red'));
balls.push(new GravityBall(150, 50, 1, 'blue', 0.8));
}
function draw() {
background(220);
for (let b of balls) {
b.move();
b.show();
}
}
Beide objecten gebruiken bijna dezelfde code, maar GravityBall heeft extra gedrag. Zo voorkom je duplicatie en blijft je programma overzichtelijk.
4. Uitbreiden zonder breken¶
Inheritance maakt het mogelijk om gedrag toe te voegen of te veranderen zonder bestaande code te breken.
class BouncingBall extends Ball {
move() {
this.x += this.speed;
if (this.x > width || this.x < 0) {
this.speed *= -1; // omkeren bij de randen
}
}
}
Nu kun je Ball, GravityBall en BouncingBall samen gebruiken, allemaal gebaseerd op dezelfde basislogica.
Denkvraag
Welke voordelen heeft dit als je in een team werkt en verschillende mensen aan verschillende soorten ballen werken?
5. Wanneer gebruik je inheritance?¶
Gebruik inheritance wanneer:
- meerdere classes veel gemeenschappelijke eigenschappen of functies delen;
- de nieuwe class een speciale vorm is van de oude (bijv. GravityBall is een Ball);
- je gedrag wilt uitbreiden, niet vervangen.
Gebruik het niet als objecten alleen maar samenwerken (zoals Game heeft een Ball) β dan gebruik je compositie in plaats van overerving.
6. Oefeningen¶
Mini-opdracht 1
Maak een ColorChangingBall class die van kleur verandert als hij beweegt. Laat hem erven van Ball.
Mini-opdracht 2
Maak een SuperBall class die zowel zwaartekracht gebruikt als kan stuiteren.
Mini-opdracht 3
Teken een UML-diagram in Mermaid waarin Ball, GravityBall, BouncingBall en SuperBall worden weergegeven.
7. Reflectie¶
Inheritance helpt je om:
- duplicatie te vermijden,
- gedrag te hergebruiken,
- en nieuwe varianten te maken zonder oude code aan te passen.
Gebruik het bewust
Te veel overerving maakt je code onnodig ingewikkeld. Als iets geen is-een relatie is, gebruik liever compositie (“heeft-een”).
Begrippen¶
- Inheritance (overerving): een class bouwt voort op een andere class.
- Parent class (superclass): de oorspronkelijke class waarvan wordt geΓ«rfd.
- Child class (subclass): de class die uitbreidt.
- super(): roept functies of constructor van de parent aan.
- extends: sleutelwoord dat overerving activeert.
- is-een-relatie: de subclass is een specifiekere vorm van de parent.