Overerving

Doel

Leer hoe klassen als basis kunnen dienen voor andere klassen. Zo hoef je functionaliteit slechts 1x te implementeren.

Aan de slag

We beginnen met een voorbeeld. Stel dat we een klasse Dog hebben. Honden kunnen wandelen en praten:

public class Dog

{

public void talk()

{

System.out.println("OMG! A talking animal!");

}

public void walk()

{

System.out.println("Walking dog here...");

}

}

Als we naar een klasse Eagle (arend in het NL), krijgen we bvb:

public class Eagle

{

public void talk()

{

System.out.println("OMG! A talking animal!");

}

public void fly()

{

System.out.println("I believe I can fly!");

}

}

Je merkt dat een arend kan vliegen! :-)

Je merkt waarschijnlijk ook dat de methode talk in beide klassen aanwezig is! Gekopieerde code is iets dat programmeurs niet zo graag zien staan... Het zou een stuk handiger zijn als we die talk-methode maar 1x moesten schrijven. Dankzij overerving kan dat!

We introduceren een nieuwe klasse, Animal, met daarin de talk-methode:

public class Animal

{

public void talk()

{

System.out.println("OMG! A talking animal!");

}

}

Nu passen we Eagle en Dog zodanig aan dat ze de klasse Animal als basis nemen:

public class Eagle extends Animal

{

public void fly()

{

System.out.println("I believe I can fly!");

}

}

public class Dog extends Animal

{

public void walk()

{

System.out.println("Walking dog here...");

}

}

We gebruiken de klassen Dog en Eagle nu in een testprogramma:

public class Test

{

public static void main (String[] args)

{

Dog dog = new Dog();

dog.talk();

dog.walk();

Eagle eagle = new Eagle();

eagle.talk();

eagle.fly();

}

}

Je merkt dat de methode talk() gewoon kan opgeroepen worden op de instanties van Dog en Eagle. Doordat Dog en Eagle overerven van Animal, is de talk() methode gewoon beschikbaar.

Voor instanties van Eagle kunnen we uiteraard de methode walk() niet oproepen. Instanties van Dog hebben dan weer geen beschikking over de methode fly().

BlueJ toont ook mooi de relatie tussen de klassen die je gebruikt:

BlueJ - Inheritance Overview

Methoden overschrijven

Je hebt ongetwijfeld al gemerkt dat alle dieren hetzelfde zeggen als je er de talk-methode van oproept ("OMG! A talking animal!"). Om dat op te lossen kunnen we de talk-methode overschrijven:

public class Dog extends Animal {

public void walk()

{

System.out.println("Walking dog here...");

}

public void talk()

{

System.out.println("Woof woof");

}

}

Als we nu dezelfde code uitvoeren als daarnet, krijgen we:

Je merkt dat de hond nu blaft ("Woof woof") als we de talk-methode oproepen! En hoewel we op de klasse Eagle dezelfde methode oproepen, geeft dit andere output ("OMG! A talking animal!").

Oefening

Overschrijf de talk methode in de klasse Eagle zelf, zodat de arend ook iets anders zegt.

Overerving en Polymorfisme

Kijk even naar volgende code en de bijhorende output:

public class Test

{

public static void main (String[] args)

{

Dog dog = new Dog();

Eagle eagle = new Eagle();

Animal animal = dog;

animal.talk();

animal = eagle;

animal.talk();

}

}

Je merkt dat we de klasse Animal kunnen gebruiken om te verwijzen naar instanties van Dog of Eagle (afgeleide klassen van Animal). Dit heet polymorfisme. Polymorfisme betekent letterlijk "meerdere vormen". In dit geval kan een instantie van Dog dus zowel als Dog en als Animal gezien worden.

Je merkt dat we de talk-methoden van Dog en Eagle kunnen oproepen door animal.talk() uit te voeren. Er wordt dus wel degelijk gekeken naar wat voor instantie (van Dog of Eagle) de animal-variabele verwijst. We roepen hier niet de talk-methode van de klasse Animal op!

Waarom is polymorfisme nu handig? Stel dat je volgende code hebt:

public class Test

{

public static void makeItTalk(Animal animal)

{

animal.talk();

}

public static void main (String[] args)

{

Dog dog = new Dog();

Eagle eagle = new Eagle();

makeItTalk(dog);

makeItTalk(eagle);

}

}

De methode makeItTalk hoeft helemaal niet te weten of de animal parameter een Dog of een Eagle is. Het enige dat de makeItTalk() methode weet is dat het iets is dat als Animal kan behandeld worden.

Dit betekent wel dat de makeItTalk() methode geen beschikking heeft over de walk() methode van Dog of de fly() methode van Eagle.

Het begin van ALLES - Object

TODO:

- Object is de parent klasse van alle klassen (ook klassen die niets extenden)

- uitleg van algemene methoden van Object (zoals equals en toString())

- opdrachtje met overriden van equals en/of toString

Abstracte klassen

TODO