Naar inhoud springen

Duck-typing

Uit Wikipedia, de vrije encyclopedie

Duck-typing is een term uit de informatica waarmee een bepaalde eigenschap van het type-systeem van een programmeertaal aangeduid wordt. In een programmeertaal met duck-typing is het mogelijk objecten aan te passen door nieuwe methoden of attributen aan deze objecten toe te voegen.

If it walks like a duck...

[bewerken | brontekst bewerken]

De term "duck-typing" is afgeleid van de (van buiten de informatica afkomstige) uitdrukking "If it walks like a duck and quacks like a duck, it is a duck." (Loopt het als een eend, en kwaakt het als een eend, dan is het een eend). Dit duidt op het feit dat een programmeertaal met duck-typing niet kijkt naar de klasse van een object om te zien wat dit object "kan", maar naar het object zelf.

Zonder duck-typing

[bewerken | brontekst bewerken]

Stel, we hebben het volgende code-fragment in een taal zonder duck-typing:

 letters = new Array(); // een array gevuld met letters
 cijfers = new Array(); // een array gevuld met getallen
letters1 = ['a', 'f', 'g']; cijfers1 = [1, 5, 8];

Nu zou het handig zijn als cijfers1 een methode totaal had, die het totaal van de in de array opgeslagen cijfers oplevert. In een taal zonder duck-typing kan dit alleen door een nieuwe klasse te maken, afgeleid van de klasse Array met één nieuwe methode:

 class Cijfers extends Array {
   int totaal() {
     // bereken en retourneer het totaal 
   }
 }
letters = new Array(); // een array gevuld met letters cijfers = new Cijfers(); // een array gevuld met getallen

Met duck-typing

[bewerken | brontekst bewerken]

In een taal met duck-typing is het toevoegen van een extra klasse niet nodig om objecten een nieuwe methode te geven. In plaats daarvan geven we het object gewoon de extra methode:

 letters = new Array(); // een array gevuld met letters
 cijfers = new Array(); // een array gevuld met getallen
 cijfers.totaal = function() { // bereken en retourneer het totaal };

Type-checking

[bewerken | brontekst bewerken]

De reden dat dit mogelijk is, heeft te maken met de manier waarop in een taal type-checking (het controleren van de types in de verschillende operaties) plaatsvindt. Neem het volgende fragment (een vervolg op het bovenstaande voorbeeld):

 print cijfers.totaal(); // goed
 print letters.totaal(); // fout! 

In een taal zonder duck-typing controleert de compiler de klasse van een object om te controleren of een bepaalde bewerking op een object mogelijk is. De eerste regel van het voorbeeld levert geen probleem op: cijfers is een object van de klasse Cijfers. Deze klasse heeft een methode totaal() en dus is er geen probleem. Bij de tweede regel kijkt de compiler van welke klasse letters een object is. Dit is de klasse Array, die geen methode totaal() heeft. Op dit moment is er sprake van een type-error en de compilatie stopt.

Type-checking met duck-typing

[bewerken | brontekst bewerken]

In een taal met duck-typing kijkt de compiler niet naar de klasse van het object, maar naar het object zelf. Als de compiler nu het bovenstaand fragment controleert weet de compiler niet of het cijfers-object een methode totaal() heeft. Deze kan immers op een eerdere plek in het programma aan het object toegevoegd zijn! Nu is dat geen probleem voor het cijfers-object: dat geven we inderdaad een extra methode totaal(). Als de compiler de volgende regel controleert weet deze ook niet of het letters-object een methode totaal() heeft. Dus ook deze regel wordt door de compiler zonder foutmelding geaccepteerd: de compilatie van het fragment verloopt zonder problemen.

Als het programma uitgevoerd wordt, is het resultaat wel een foutmelding. Bij de regel print letters.totaal(); aangekomen, zoekt het programma tevergeefs naar een methode totaal() van het letters-object. Een runtime error is het gevolg.

Voor- en nadelen

[bewerken | brontekst bewerken]

Een belangrijk verschil tussen een taal zonder duck-typing en een taal met duck-typing is dus dat de eerste meer fouten kan ontdekken door middel van type-checking, dus tijdens het compileren. Dit betekent dat bugs sneller ontdekt worden en programma's veiliger zijn. Bij duck-typing komen fouten pas tijdens het draaien van het programma aan het licht, en niet noodzakelijk tijdens iedere uitvoering van het programma: er moet extra getest worden.

Hier staat tegenover dat de programmeur meer vrijheid heeft en een taal met duck-typing expressiever is. Programma's zijn vaak korter, met minder "huishoudelijke" code.

  • Uit de manier waarop duck-typing werkt volgt ook dat talen met duck-typing altijd zwak-getypeerd zijn, en ook altijd tot op zekere hoogte (of helemaal) dynamisch getypeerd.
  • Behalve het toevoegen van methoden kunnen er bij duck-typing ook methoden van objecten verwijderd worden. Ook is het mogelijk in plaats van methoden attributen aan een object toe te voegen.
  • Voorbeelden van talen met duck-typing zijn JavaScript, Python, Smalltalk, Dart en Ruby.