Skip to content
Programmeren in Python, leer de nieuwste technieken
Programmeren in PythonProgrammeren in Python
  • Home
  • Blog
  • Documentatie
  • Cursussen
Programmeren in PythonProgrammeren in Python
  • Home
  • Blog
  • Documentatie
  • Cursussen

Introductie

4
  • 1.1 Wat is Python?
  • 1.2 Python installatie
  • 1.2.1 Python installeren voor MacOS
  • 1.3 PyCharm Installatie

Basisprogrammering

6
  • 2.1 Python Basis: Variabelen, Datatypes en Operatoren
  • 2.2 Python if else (en elif)
  • 2.3 Python list (Array, Lijsten)
  • 2.4 Python Lussen: for loop, while loop, break, continue
  • 2.5 Python Functies: Definities, Parameters en Terugkeerwaarden
  • 2.6 Foutafhandeling: try, except, else, finally

Datatypes

13
  • 3.1 Introductie tot Geavanceerde Datatypes
  • 3.2 Python Tuple
  • 3.3 Python Set
  • 3.4 Python Dictionary
  • 3.5 Werken met Strings en String-methoden
  • 3.6 Collections Module: Krachtige Tools in Python
  • 3.7 Iterators en Generators
  • 3.8 List Comprehensions
  • 3.9 Geavanceerde Sortering
  • 3.10 Werken met Multi-dimensionale Data
  • 3.11 Typing en Datatypes
  • 3.12 Itertools voor Geavanceerde Iteraties
  • 3.13 Data Conversies

Modules

8
  • 4.1 Wat zijn Modules en Waarom zijn ze Belangrijk?
  • 4.2 Werken met Ingebouwde Modules
  • 4.3 Installeren en Gebruiken van Externe Pakketten
  • 4.4 Eigen Modules Maken
  • 4.5 Introductie tot Pakketten
  • 4.6 Importeren en Namespaces Begrijpen
  • 4.7 Geavanceerd: Relatief Importeren
  • 4.8 Organiseren van Grotere Projecten

Data Analyse

3
  • 5.1 Python Dataframe en Data Opschonen met Pandas
  • 5.2 Python Pandas Basisstatistieken en Data-analyse
  • 5.3 Python Numpy (NpArray): De Kracht van Numerieke Berekeningen

Webontwikkeling

5
  • 7.1 Inleiding tot Webontwikkeling
  • 7.2 HTTP-Verzoeken met requests: Communiceren met het Web
  • 7.3 Webscraping met BeautifulSoup: Data van het Web Halen als er geen APIs zijn
  • 7.4 Python Flask, een webserver & API tutorial
  • 7.5 WSGI & WebOb

Deploy

1
  • Deploy met Supervisor op Ubuntu

Object Georiënteerd Programmeren

8
  • Wat is Objectgeoriënteerd Programmeren (OOP) in Python?
  • Python class & object maken
  • self en __init__ uitgelegd (met voorbeelden)
  • Attributen afschermen: @property (getters/setters)
  • Overerving in Python + super() (en wanneer je het beter níet doet)
  • Dunder methods: __str__, __repr__, vergelijken (en waarom dit je OOP-code “Pythonic” maakt)
  • @dataclass: snelle nette classes (minder boilerplate, meer duidelijkheid)
  • OOP in de praktijk: design & structuur
View Categories
  • Home
  • Documentatie
  • Object Georiënteerd Programmeren
  • Overerving in Python + super() (en wanneer je het beter níet doet)

Overerving in Python + super() (en wanneer je het beter níet doet)

6 minuten leestijd

Na dit hoofdstuk snap je:

  • wat overerving is in Python en wanneer je het gebruikt,
  • het verschil tussen “is-een” en “heeft-een” (inheritance vs compositie),
  • hoe method overriding werkt,
  • wat super() precies doet en waarom je het bijna altijd wilt,
  • en de meest gemaakte fouten (vergeten super().__init__(), verkeerde “is-a” relatie, rare bugs bij multiple inheritance).

1. Wat is overerving? #

Overerving betekent: je maakt een subclass die eigenschappen en gedrag erft van een base class.

  • Base class: algemene versie (bv. Car)
  • Subclass: gespecialiseerde versie (bv. ElectricCar)
class Car:
    def start(self):
        return "Engine started"

class ElectricCar(Car):
    pass

e = ElectricCar()
print(e.start())  # erft start() van Car
Python

Waarom zou je dit doen?

  • Je wil gedeelde logica op één plek hebben (DRY).
  • Je wil een “speciale variant” maken die net iets anders doet.

2. De belangrijkste vraag: “is-een” of “heeft-een”? #

Dit voorkomt 80% van de ontwerp-fouten.

Overerving = “is-een”

ElectricCar is een Car.

Goed:

  • ElectricCar is een Car
  • Student is een Person
  • AdminUser is een User (soms)

Compositie = “heeft-een”

Een Car heeft een Engine → dus geen inheritance.

Goed:

  • Car heeft Engine
  • Order heeft CartItems
  • EmailService heeft een Client

Vuistregel:

Als je zin logisch klopt met “is een”, dán pas is overerving verdedigbaar.

3. Method overriding: gedrag aanpassen in een subclass #

Een subclass kan een methode overschrijven (override) om ander gedrag te geven.

class Car:
    def start(self):
        return "Engine started"

class ElectricCar(Car):
    def start(self):
        return "Electric motor started"

print(Car().start())         # Engine started
print(ElectricCar().start()) # Electric motor started
Python

Hier gebeurt iets belangrijks:

  • Python kijkt naar het type van het object (runtime).
  • ElectricCar().start() gebruikt de override.

Dat is al een vorm van polymorfisme.


4. Waar past super() in dit verhaal? #

Veel overrides willen niet alles vervangen, maar iets toevoegen aan het basisgedrag.

Dán gebruik je super().

Waarom niet gewoon Car.start(self) aanroepen?

Dat kan, maar super() is:

  • netter (minder hardcoded),
  • beter bij refactors,
  • essentieel bij multiple inheritance (cooperative).

Voorbeeld: basisgedrag uitbreiden

class Car:
    def start(self):
        return "Engine started"

class RacingCar(Car):
    def start(self):
        base = super().start()
        return base + " with race mode"

print(RacingCar().start())
# Engine started with race mode
Python

Wat betekent super() hier concreet?

  • Het is een manier om “de volgende implementatie in de inheritance-keten” te pakken.
  • Niet “de parent class” in het algemeen, maar volgens de MRO (daarover zo meer).

5. De meest voorkomende fout: super().__init__() vergeten #

Als je base class __init__ attributen zet, en jij overschrijft __init__ in een subclass, dan moet je meestal de base init ook draaien.

Fout

class Vehicle:
    def __init__(self, brand):
        self.brand = brand

class Car(Vehicle):
    def __init__(self, brand, doors):
        self.doors = doors

c = Car("Volvo", 5)
print(c.brand)  # AttributeError: brand bestaat niet
Python

Je base class deed het werk (brand zetten), maar je hebt het nooit aangeroepen.

Goed

class Vehicle:
    def __init__(self, brand):
        self.brand = brand

class Car(Vehicle):
    def __init__(self, brand, doors):
        super().__init__(brand)  # base init
        self.doors = doors

c = Car("Volvo", 5)
print(c.brand)  # Volvo
Python

Waarom is dit “beter ontwerp”?

  • Base class blijft verantwoordelijk voor base-state.
  • Subclass voegt alleen extra state toe.
  • Minder dubbel werk, minder bugs.

6. Wanneer overerving onhandig wordt (en compositie beter is) #

Overerving gaat vaak mis als je overerving gebruikt voor “features” i.p.v. een echte “is-a” relatie.

Slecht teken: je wil meerdere “eigenschappen mixen”

Bijvoorbeeld: je wil een Car die:

  • elektrisch is
  • én luxe is
  • én sport is

Dan krijg je al snel:

  • LuxuryElectricSportsCar (Dit gaat nooit werken zo…)

Dat is een hint dat je beter compositie gebruikt.

Compositie-voorbeeld: Car + Engine

class Engine:
    def __init__(self, kind):
        self.kind = kind

    def start(self):
        return f"{self.kind} engine started"

class Car:
    def __init__(self, brand, engine: Engine):
        self.brand = brand
        self.engine = engine

    def start(self):
        return self.engine.start()

car = Car("Tesla", Engine("electric"))
print(car.start())  # electric engine started
Python

Waarom dit fijner is dan inheritance?

  • Je kunt engine wisselen zonder subclass-explosie.
  • Gedrag is “plugbaar”.

7. Multiple inheritance en MRO (alleen wat je écht moet weten) #

Python kan meerdere base classes hebben:

class A: ...
class B: ...
class C(A, B): ...
Python

Dan moet Python weten: als C een methode niet heeft, zoek ik eerst in A of in B?

Dat regelt Python met de MRO (Method Resolution Order).

Je kunt het zien met:

print(C.__mro__)
Python

Waarom is dit relevant voor super()?

Omdat super() niet “gewoon de parent” is, maar “de volgende class in de MRO”.

Dit is precies waarom super() de voorkeur heeft boven BaseClass.method(self).

Praktische tip:

  • Gebruik multiple inheritance vooral voor mixins (kleine herbruikbare stukjes gedrag).
  • Als je MRO niet snapt, hou het simpel en kies compositie.

8. Voorbeeld: Notifications #

Je wil verschillende notificaties: email, sms, push.
Overerving kan, maar vaak is het slimmer als polymorfisme/compositie. Toch is dit een nette “is-a” case:

class Notifier:
    def send(self, message):
        raise NotImplementedError

class EmailNotifier(Notifier):
    def send(self, message):
        print(f"Email: {message}")

class SMSNotifier(Notifier):
    def send(self, message):
        print(f"SMS: {message}")

def alert(notifier: Notifier, message):
    notifier.send(message)

alert(EmailNotifier(), "Hi!")
alert(SMSNotifier(), "Hi!")
Python

Dit laat zien:

  • “is-a”: EmailNotifier is een Notifier
  • polymorfisme: alert() werkt met elke notifier met send()

Nu je overerving hebt geleerd is het belangrijk om nog meer standaard functies te kennen die betrekking hebben op de verschillende objecten. Zie het volgende hoofdstuk voor de ‘Dunder’ methods.

Updated on januari 4, 2026

What are your Feelings

Attributen afschermen: @property (getters/setters)Dunder methods: __str__, __repr__, vergelijken (en waarom dit je OOP-code “Pythonic” maakt)
Inhoudsopgave
  • 1. Wat is overerving?
  • 2. De belangrijkste vraag: “is-een” of “heeft-een”?
  • 3. Method overriding: gedrag aanpassen in een subclass
  • 4. Waar past super() in dit verhaal?
  • 5. De meest voorkomende fout: super().__init__() vergeten
  • 6. Wanneer overerving onhandig wordt (en compositie beter is)
  • 7. Multiple inheritance en MRO (alleen wat je écht moet weten)
  • 8. Voorbeeld: Notifications
Programmeren in Python

Leer python op je eigen tempo met mooie interactieve hedendaagse voorbeelden.

© Copyright 2026 Programmeren in Python.
Sign inSign up

Sign in

Don’t have an account? Sign up
Lost your password?

Sign up

Already have an account? Sign in