Polymorfisme

Doel

Leer hoe je met behulp van polymorfisme code herbruikbaar maakt en daardoor minder code moet schrijven.

Sommige delen van je code lijken sterk op mekaar, maar doen net wat anders. Stel dat je een kat en een hond hebt. Beide kunnen een geluid maken, maar maken een ander geluid. De kat miauwt en de hond blaft. Maar je wilt de code die de kat aanspoort om een geluid te maken niet kopiëren voor de hond.

Aan de slag

1. Een interface toevoegen

Klik op de knop New Class, maar kies deze keer voor een Interface in plaats van een Class. We maken een interface Animal die zowel Cat als Dog zullen implementeren.

Een interface is een specificatie, een contract. Het zegt wat een object kan doen zonder te zeggen hoe dat precies moet. Methodes in een interface hebben dan ook geen inhoud. Na de definitie van de naam en de parameters komt er direct een puntkomma, geen accolades. We voegen een methode makeSound() toe, die zowel Cat als Dog invulling zullen geven, omdat katten en honden nu eenmaal een ander geluid maken.

INTERFACE

public interface Animal { void makeSound();}

2. Een interface implementeren

Nadat we een interface geschreven hebben maken we een implementatie van de interface. Een implementatie is een klasse die invulling geeft aan alle methodes in de interface. Dus elke methode die gedefinieerd is door de interface moet ook in de implementatie staan. Maak een nieuwe klasse Dog en laat de klasse de interface Animal implementeren. Dit doe je door implements Animal te schrijven na de naam van de klasse.

IMPLEMENTATIE

public class Dog implements Animal {}

Compileer nu je klasse. Je zal merken dat dit niet lukt.

De interface Animal bevat de methode makeSound(), dus moet ook Dog die bevatten. Voeg de methode toe en laat de hond een overtuigend geluid maken. Met @Override annotatie voor de methode duiden we aan dat we de methode van de interface overschrijven. Dit is niet verplicht, maar het is een goede gewoonte, want de compiler zal je erop wijzen wanneer dit niet langer het geval is. Stel dat je makeSound() in Animal van naam wijzigt, maar in Dog niet, zal de compiler je daarop attent maken.

IMPLEMENTATIE VAN EEN METHODE

public class Dog implements Animal { @Override public void makeSound() { System.out.println("Woef!"); }}

Maak nu een klasse Cat analoog aan Dog die het juiste geluid maakt.

3. Een interface gebruiken

Nu tonen we de ware kracht van een interface. We maken een lijst van dieren en we laten ze allemaal een geluid maken met 3 eenvoudige lijntjes code. Maak een nieuwe klasse Animals en voeg een static methode makeSounds() toe.

STATIC METHODE

public class Animals { public static void makeSounds() { }}

Nu maken we een lijst van dieren. Daarvoor hebben we twee imports nodig: java.util.List en java.util.Arrays.

LIST EN ARRAYS

import java.util.List;import java.util.Arrays;public class Animals { public static void makeSounds() { List<Animal> animals = Arrays.asList(new Cat(), new Dog(), new Dog(), new Dog()); } }

Deze lijn code toont meteen twee interfaces in actie! List is een interface voor lijsten die verschillende implementaties heeft. Arrays.asList() is een methode die een implementatie van interface teruggeeft. Welke, dat weet je niet, maar dat maakt niet uit. Zolang het object maar aan het contract van List voldoet. Ook de interface Animal zien we hier in actie. List heeft een generieke parameter die je tussen <> schrijft. Daarmee zeg je: het is een lijst van dieren. In die lijst kun je zowel katten als honden steken, omdat ze allebei dieren zijn. We kunnen ook eenvoudig alle katten en honden een geluid laten maken zonder op voorhand te hoeven weten of het om een kat of een hond gaat.

LAAT ALLE DIEREN EEN GELUID MAKEN

public static void makeSounds() { List<Animal> animals = Arrays.asList(new Cat(), new Dog(), new Dog(), new Dog()); for(Animal animal : animals) { animal.makeSound(); } }

De for-lus loopt over alle dieren in de lijst. Elk dier wordt om de beurt aan de variabele animal van het type Animal toegewezen. Omdat zowel Cat als Dog de methode makeSound() implementeren, kun je gewoon animal.makeSound() aanroepen zonder op voorhand te moeten weten of het om een kat of een hond gaat.

En voila! alle dieren maken een geluid!

Proficiat! Je hebt geleerd hoe je met behulp van interfaces code herbruikbaar kunt maken voor verschillende gelijkaardige klassen.