Door gebruik te maken van overerving kan je een klasse - afgeleide klasse of subklasse genoemd - afleiden van een andere klasse - basisklasse of superklasse genoemd -.
Java is werkelijk een objectgeoriënteerde taal, die in sterke mate op overerving steunt. De ontwikkelaars van Sun hebben enorme pakketten -klassenbibliotheken- gemaakt vol met klassen die jij als superklasse kan gebruiken. Dit is belangrijk als je bijvoorbeeld een applet wenst te maken, omdat je in dat geval je applet kan afleiden van de klasse Applet in het pakket java.applet.
Je zal ook steeds gebruik maken van overerving als je visuele componenten zoals tekstvakken, keuzelijsten en knoppen op het scherm wil zetten.
In feite kan je zelfs bij het afhandelen van muisklikken niet om overerving heen. Dit keer kan je dat doen door gebruik te maken van interfaces.
Subklasse en superklasse
Een subklasse maken
We maken hieronder een klasse Vervoermiddel met een methode starten, we gaan er dus van uit dat je een Vervoermiddel kan starten.
We maken daarna een klasse Auto. De klasse Auto bevat een methode rijden. Daar niet elk Vervoermiddel bestemd is om te rijden (denk maar aan boten of vliegtuiden) definiëren we hiervoor een nieuwe klasse. Een Autois eenVervoermiddel, een Auto kan je dus ook starten. Het zou vervelend zijn dat je voor elk specifiek Vervoermiddel waarvoor je een klasse aanmaakt de methode starten (en alle andere mogelijkheden van de klasse Vervoermiddel) opnieuw zou moeten maken.
We kunnen ervoor zorgen dat de klasse Auto automatisch de mogelijkheden (variabelen, methodes,...) van de klasse Vervoermiddel overerft.
We noemen Auto een subklasse van Vervoermiddel en Vervoermiddel de superklasse van Auto.
De klasse Progvervoer fungeert als hoofprogramma, het is steeds een goed idee de hoofdstructuur van je programma (de eigenlijk werking-acties van je programma) onder te brengen in een aparte klasse.
public class Vervoermiddel {
public void starten(){
System.out.println("Aan het starten...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto();
a.starten();
a.rijden();
}
}
Uitvoer:
Auto aan het maken...
Aan het rijden...
Aan het starten...
Toegangsaanduiders
Denk er nu aan de juiste toegangsaanduider (private, protected, public, geen aanduider) te gebruiken voor je methoden.
Hier een overzicht van de plaatsen waar je toegang hebt tot een methode met de verschillende toegangsaanduiders:
Plaats
Private
Geen aanduider
Protected
Public
Zelfde klasse
x
x
x
x
Subklasse in hetzelfde pakket
x
x
x
Niet-subklasse in hetzelfde pakket
x
x
x
Subklasse in een ander pakket
x
x
Niet-subklasse in een ander pakket
x
Wil je de methode starten enkel toegankelijk maken tot subklassen van de klasse Vervoermiddel dan kan je de toegangsaanduider protected gebruiken.
Toon volledige code...Toon nieuwe code...
public class Vervoermiddel {
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto();
a.starten();
a.rijden();
}
}
public class Vervoermiddel {
protected void starten(){
System.out.println("Aan het starten...");
}
}
...
Daar je in de klasse app een object van de subklasse Auto aanmaakt kan je van hieruit de methode starten gebruiken.
Constructoren gebruiken
Stel dat je in de superklasse Vervoermiddel een constructor aanbrengt die geen parameters aanvaard:
Toon volledige code...Toon nieuwe code...
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto();
a.starten();
a.rijden();
}
}
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
...
Uitvoer:
Auto aan het maken...
Ik ben een vervoermiddel...
Aan het rijden...
Aan het starten...
Nu breng je ook een constructor zonder parameters aan in de subklasse Auto:
Toon volledige code...Toon nieuwe code...
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto();
a.starten();
a.rijden();
}
}
...
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
...
Uitvoer:
Auto aan het maken...
Ik ben een vervoermiddel...
Ik ben een auto...
Aan het rijden...
Aan het starten...
Je merkt dat beide constructoren worden uitgevoerd bij het maken van een instantie van de klasse Auto.
Eerst wordt de constructor uit de superklasse Vervoermiddel uitgevoerd, daarna de constructor uit de subklasse Auto.
We voegen nog een constructor in de klasse auto toe, deze ontvangt een String-waarde:
Toon volledige code...Toon nieuwe code...
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public Auto(String s){
System.out.println("Stringconstructor Auto: " +s);
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...");
a.starten();
a.rijden();
}
}
...
public class Auto extends Vervoermiddel{
...
public Auto(String s){
System.out.println("Stringconstructor Auto: " +s);
}
...
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...");
a.starten();
a.rijden();
}
}
Uitvoer:
Auto aan het maken...
Ik ben een vervoermiddel...
Stringconstructor Auto: Vroem...
Aan het rijden...
Aan het starten...
Je merkt dat de constructor uit subklasse Auto die geen parameters ontvangt niet meer wordt uitgevoerd. De constructor uit de superklasse Vervoermiddel wordt wel nog uitgevoerd!
Een constructor zonder parameters in een superklasse wordt de standaardconstructor voor een klasse genoemd en zal steeds uitgevoerd worden wanneer je subklassen van die klasse afleidt, tenzij je andere maatregelen neemt.
Voeg je ook een stringconstructor toe aan de superklasse Vervoermiddel dan blijft de uitvoer hetzelfde, de String-constructor uit de superklasse wordt dus niet uitgevoerd!
Toon volledige code...Toon nieuwe code...
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public Auto(String s){
System.out.println("Stringconstructor Auto: " +s);
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...");
a.starten();
a.rijden();
}
}
public class Vervoermiddel {
...
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
...
}
...
Uitvoer:
Auto aan het maken...
Ik ben een vervoermiddel...
Stringconstructor Auto: Vroem...
Aan het rijden...
Aan het starten...
Als je een constructor met parameters uit de superklasse wenst uit te voeren moet je dat expliciet aangeven, en moet je de parameter ook nog eens meegeven aan die superklasse:
Toon volledige code...Toon nieuwe code...
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public Auto(String s){
super(s);
System.out.println("Stringconstructor Auto: " +s);
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...");
a.starten();
a.rijden();
}
}
...
public class Auto extends Vervoermiddel{
...
public Auto(String s){
super(s);
System.out.println("Stringconstructor Auto: " +s);
}
...
}
...
Uitvoer:
Auto aan het maken...
Strinconstructor Vervoermiddel: Vroem...
Stringconstructor Auto: Vroem...
Aan het rijden...
Aan het starten...
Nu wordt de stringconstructor van klasse Vervoermiddel aangeroepen en niet de standaardconstructor van de klasse Vervoermiddel (de cosntructor zonder parameters).
Een aanroep naar super moet het eerste statement zijn in een constructor.
Overerving op meerdere niveaus
Principes van meervoudige overerving
We voegen nog een klasse toe aan ons programma Progvervoer.
We zorgen ervoor dat we ook vliegende vervoermiddelen kunnen gebruiken met de klasse Luchtvaartuig.
Instanties van deze klasse beschikken over een methode vliegen.
public class Luchtvaartuig extends Vervoermiddel {
public void vliegen(){
System.out.println("Aan het vliegen...");
}
}
Wanneer we nu twee types vliegende Vervoermiddelen hebben: Wentelwieken die kunnen wentelen en Jets die kunnen zoeven, kunnen we twee klassen aanmaken die afgeleid zijn van de klasse Luchtvaartuig: Wentelwiek en Jet.
public class Wentelwiek extends Luchtvaartuig{
public void wentelen(){
System.out.println("Aan het wentelen...");
}
}
public class Jet extends Luchtvaartuig{
public void zoeven(){
System.out.println("Aan het zoeven...");
}
}
We doen nu de nodige aanpassingen in Progvervoer zodanig dat we met een Jet het luchtruim ingaan:
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...");
a.starten();
a.rijden();
System.out.println("");
System.out.println("Jet aan het maken...");Jet j = new Jet();j.starten();j.vliegen();j.zoeven();
}
}
Uitvoer: (met betrekking tot de Jet)
Jet aan het maken...
Ik ben een vervoermiddel...
Aan het starten...
Aan het vliegen...
Aan het zoeven...
De Jetj kan dus:
De methode starten uit de klasse Vervoermiddel gebruiken
De methode vliegen uit de klasse Luchtvaartuig gebruiken
De methode zoeven uit de klasse Jet gebruiken
Constructoren bij meervoudige overerving: standaardconstructoren
We voegen nu ook parameterloze constructoren toe aan de verschillende klassen:
Toon volledige code...Toon nieuwe code...
public class Luchtvaartuig extends Vervoermiddel {
public Luchtvaartuig(){
System.out.println("Ik ben een luchtvaartuig...");
}
public void vliegen(){
System.out.println("Aan het vliegen...");
}
}
public class Wentelwiek extends Luchtvaartuig{
public void Wentelwiek(){
System.out.println("Ik ben een Wentelwiek...");
}
public void wentelen(){
System.out.println("Aan het wentelen...");
}
}
public class Jet extends Luchtvaartuig{
public Jet(){
System.out.println("Ik ben een Jet...");
}
public void zoeven(){
System.out.println("Aan het zoeven...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public Auto(String s){
super(s);
System.out.println("Stringconstructor Auto: " +s);
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...");
a.starten();
a.rijden();
System.out.println("");
System.out.println("Jet aan het maken...");
Jet j = new Jet();
j.starten();
j.vliegen();
j.zoeven();
}
}
public class Luchtvaartuig extends Vervoermiddel {
public Luchtvaartuig(){
System.out.println("Ik ben een luchtvaartuig...");
}
...
}
public class Wentelwiek extends Luchtvaartuig{
public void Wentelwiek(){
System.out.println("Ik ben een Wentelwiek...");
}
...
}
public class Jet extends Luchtvaartuig{
public Jet(){
System.out.println("Ik ben een Jet...");
}
...
}
...
Uitvoer: (met betrekking tot de Jet)
Jet aan het maken...
Ik ben een vervoermiddel...
Ik ben een luchtvaartuig...
Ik ben een Jet...
Aan het starten...
Aan het vliegen...
Aan het zoeven...
De uitvoer van de constructoren gaat dus in de volgorde: eerst superklasse, daarna subklasse.
Gebruik van super bij parameterconstructoren
We voegen nu Stringconstructoren toe aan de subklassen die we hebben toegevoegd:
Toon volledige code...Toon nieuwe code...
public class Luchtvaartuig extends Vervoermiddel {
public Luchtvaartuig(){
System.out.println("Ik ben een luchtvaartuig...");
}
public Luchtvaartuig(String s){
System.out.println("Stringconstructor Luchtvaartuig: " +s);
}
public void vliegen(){
System.out.println("Aan het vliegen...");
}
}
public class Wentelwiek extends Luchtvaartuig{
public Wentelwiek(){
System.out.println("Ik ben een Wentelwiek...");
}
public Wentelwiek(String s){
System.out.println("Stringconstructor Wentelwiek: " +s);
}
public void wentelen(){
System.out.println("Aan het wentelen...");
}
}
public class Jet extends Luchtvaartuig{
public Jet(){
System.out.println("Ik ben een Jet...");
}
public Jet(String s){
System.out.println("Stringconstructor Jet: " +s);
}
public void zoeven(){
System.out.println("Aan het zoeven...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public Auto(String s){
super(s);
System.out.println("Stringconstructor Auto: " +s);
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...");
a.starten();
a.rijden();
System.out.println("");
System.out.println("Jet aan het maken...");
Jet j = new Jet("Zoef !!");
j.starten();
j.vliegen();
j.zoeven();
}
}
public class Luchtvaartuig extends Vervoermiddel {
...
public Luchtvaartuig(String s){
System.out.println("Stringconstructor Luchtvaartuig: " +s);
}
...
}
public class Wentelwiek extends Luchtvaartuig{
...
public Wentelwiek(String s){
System.out.println("Stringconstructor Wentelwiek: " +s);
}
...
}
public class Jet extends Luchtvaartuig{
...
public Jet(String s){
System.out.println("Stringconstructor Jet: " +s);
}
...
}
...
Uitvoer: (met betrekking tot de Jet)
Jet aan het maken...
Ik ben een vervoermiddel...
Ik ben een luchtvaartuig...
Stringconstructor Jet: Zoef !!
Aan het starten...
Aan het vliegen...
Aan het zoeven...
De constructoren zonder parameters uit de superklassen Vervoermiddel en Luchtvaartuig worden uitgevoerd, dit zijn hier de standaardconstructoren.
Uit de klasse Jet wordt enkel de String-constructor uitgevoerd.
Pas nu de code als volgt aan:
Toon volledige code...Toon nieuwe code...
public class Luchtvaartuig extends Vervoermiddel {
public Luchtvaartuig(){
System.out.println("Ik ben een luchtvaartuig...");
}
public Luchtvaartuig(String s){
System.out.println("Stringconstructor Luchtvaartuig: " +s);
}
public void vliegen(){
System.out.println("Aan het vliegen...");
}
}
public class Wentelwiek extends Luchtvaartuig{
public Wentelwiek(){
System.out.println("Ik ben een Wentelwiek...");
}
public Wentelwiek(String s){
System.out.println("Stringconstructor Wentelwiek: " +s);
}
public void wentelen(){
System.out.println("Aan het wentelen...");
}
}
public class Jet extends Luchtvaartuig{
public Jet(){
System.out.println("Ik ben een Jet...");
}
public Jet(String s){
super(s);
System.out.println("Stringconstructor Jet: " +s);
}
public void zoeven(){
System.out.println("Aan het zoeven...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public Auto(String s){
super(s);
System.out.println("Stringconstructor Auto: " +s);
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...");
a.starten();
a.rijden();
System.out.println("");
System.out.println("Jet aan het maken...");
Jet j = new Jet("Zoef !!");
j.starten();
j.vliegen();
j.zoeven();
}
}
...
public class Jet extends Luchtvaartuig{
...
public Jet(String s){
super(s);
System.out.println("Stringconstructor Jet: " +s);
}
...
}
...
Uitvoer: (met betrekking tot de Jet)
Jet aan het maken...
Ik ben een vervoermiddel...
Stringconstructor Luchtvaartuig: Zoef !!
Stringconstructor Jet: Zoef !!
Aan het starten...
Aan het vliegen...
Aan het zoeven...
Nu wordt uit de klasse Vervoermiddel de standaardconstructor uitgevoerd en uit de klassen Luchtvaartuig en Jet de string-constructor.
Het sleutelwoord super geeft dus enkel de opdracht de constructor toe te passen in de directe superklasse van de huidige klasse. Heeft die superklasse nog een superklasse, dan wordt niet automatisch de constructor meegegeven.
We kunnen de klasse Luchtvaartuig nu als volgt aanpassen:
Toon volledige code...Toon nieuwe code...
public class Luchtvaartuig extends Vervoermiddel {
public Luchtvaartuig(){
System.out.println("Ik ben een luchtvaartuig...");
}
public Luchtvaartuig(String s){
super(s);
System.out.println("Stringconstructor Luchtvaartuig: " +s);
}
public void vliegen(){
System.out.println("Aan het vliegen...");
}
}
public class Wentelwiek extends Luchtvaartuig{
public Wentelwiek(){
System.out.println("Ik ben een Wentelwiek...");
}
public Wentelwiek(String s){
System.out.println("Stringconstructor Wentelwiek: " +s);
}
public void wentelen(){
System.out.println("Aan het wentelen...");
}
}
public class Jet extends Luchtvaartuig{
public Jet(){
System.out.println("Ik ben een Jet...");
}
public Jet(String s){
super(s);
System.out.println("Stringconstructor Jet: " +s);
}
public void zoeven(){
System.out.println("Aan het zoeven...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public Auto(String s){
super(s);
System.out.println("Stringconstructor Auto: " +s);
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...");
a.starten();
a.rijden();
System.out.println("");
System.out.println("Jet aan het maken...");
Jet j = new Jet("Zoef !!");
j.starten();
j.vliegen();
j.zoeven();
}
}
...
public class Luchtvaartuig extends Vervoermiddel {
...
public Luchtvaartuig(String s){
super(s);
System.out.println("Stringconstructor Luchtvaartuig: " +s);
}
...
}
...
Uitvoer: (met betrekking tot de Jet)
Jet aan het maken...
Stringconstructor Vervoermiddel: Zoef !!
Stringconstructor Luchtvaartuig: Zoef !!
Stringconstructor Jet: Zoef !!
Aan het starten...
Aan het vliegen...
Aan het zoeven...
Je merkt dat nu voor de klassen Vervoermiddel, Luchtvaartuig en Jet de string-constructor wordt gebruikt.
Methoden vervangen - overriden
Je kan in een subklasse een methode uit een superklasse vervangen.
Doe volgend aanpassing in de klasse Luchtvaartuig:
Toon volledige code...Toon nieuwe code...
public class Luchtvaartuig extends Vervoermiddel {
public Luchtvaartuig(){
System.out.println("Ik ben een luchtvaartuig...");
}
public Luchtvaartuig(String s){
super(s);
System.out.println("Stringconstructor Luchtvaartuig: " +s);
}
public void starten(){
System.out.println("Aan het starten, klaar om op te stijgen...");
}
public void vliegen(){
System.out.println("Aan het vliegen...");
}
}
public class Wentelwiek extends Luchtvaartuig{
public Wentelwiek(){
System.out.println("Ik ben een Wentelwiek...");
}
public Wentelwiek(String s){
System.out.println("Stringconstructor Wentelwiek: " +s);
}
public void wentelen(){
System.out.println("Aan het wentelen...");
}
}
public class Jet extends Luchtvaartuig{
public Jet(){
System.out.println("Ik ben een Jet...");
}
public Jet(String s){
super(s);
System.out.println("Stringconstructor Jet: " +s);
}
public void zoeven(){
System.out.println("Aan het zoeven...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public Auto(String s){
super(s);
System.out.println("Stringconstructor Auto: " +s);
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...");
a.starten();
a.rijden();
System.out.println("");
System.out.println("Jet aan het maken...");
Jet j = new Jet("Zoef !!");
j.starten();
j.vliegen();
j.zoeven();
}
}
...
public class Luchtvaartuig extends Vervoermiddel {
...
public void starten(){
System.out.println("Aan het starten, klaar om op te stijgen...");
}
...
}
...
Uitvoer: (met betrekking tot de Jet)
Jet aan het maken...
Stringconstructor Vervoermiddel: Zoef !!
Stringconstructor Luchtvaartuig: Zoef !!
Stringconstructor Jet: Zoef !!
Aan het starten, klaar om op te stijgen...
Aan het vliegen...
Aan het zoeven...
De methode starten in de klasse Luchtvaartuig vervangt de methode starten uit de superklasse Vervoermiddel.
De werkwijze is dus heel eenvoudig, definiëer de methode gewoon opnieuw in een subklasse.
Vervangen is niet hetzelfde als overloaden: bij overloaden definiëer je de methode meerdere keren in dezelfde klasse, doch met andere argumenten.
Je kan echter nog steeds toegang krijgen tot de vervangen methode door in de klasse een methode toe die de vervangen methode oproept met het sleutelwoord super.
Toon volledige code...Toon nieuwe code...
public class Luchtvaartuig extends Vervoermiddel {
public Luchtvaartuig(){
System.out.println("Ik ben een luchtvaartuig...");
}
public Luchtvaartuig(String s){
super(s);
System.out.println("Stringconstructor Luchtvaartuig: " +s);
}
public void starten(){
System.out.println("Aan het starten, klaar om op te stijgen...");
}
public void superstarten(){
super.starten();
}
public void vliegen(){
System.out.println("Aan het vliegen...");
}
}
public class Wentelwiek extends Luchtvaartuig{
public Wentelwiek(){
System.out.println("Ik ben een Wentelwiek...");
}
public Wentelwiek(String s){
System.out.println("Stringconstructor Wentelwiek: " +s);
}
public void wentelen(){
System.out.println("Aan het wentelen...");
}
}
public class Jet extends Luchtvaartuig{
public Jet(){
System.out.println("Ik ben een Jet...");
}
public Jet(String s){
super(s);
System.out.println("Stringconstructor Jet: " +s);
}
public void zoeven(){
System.out.println("Aan het zoeven...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public Auto(String s){
super(s);
System.out.println("Stringconstructor Auto: " +s);
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...");
a.starten();
a.rijden();
System.out.println("");
System.out.println("Jet aan het maken...");
Jet j = new Jet("Zoef !!");
j.superstarten();
j.vliegen();
j.zoeven();
}
}
...
public class Luchtvaartuig extends Vervoermiddel {
...
public void superstarten(){
super.starten();
}
...
}
public class Progvervoer {
...
System.out.println("Jet aan het maken...");
Jet j = new Jet("Zoef !!");
j.superstarten();
j.vliegen();
j.zoeven();
}
}
Uitvoer: (met betrekking tot de Jet)
Jet aan het maken...
Stringconstructor Vervoermiddel: Zoef !!
Stringconstructor Luchtvaartuig: Zoef !!
Stringconstructor Jet: Zoef !!
Aan het starten, klaar om op te stijgen...
Aan het vliegen...
Aan het zoeven...
Superklassevariabelen gebruiken met afgeleide objecten
Je kan in Java een objectreferentie van een subklasse toewijzen aan een object van een superklasse:
Toon volledige code...Toon nieuwe code...
public class Luchtvaartuig extends Vervoermiddel {
public Luchtvaartuig(){
System.out.println("Ik ben een luchtvaartuig...");
}
public Luchtvaartuig(String s){
super(s);
System.out.println("Stringconstructor Luchtvaartuig: " +s);
}
public void starten(){
System.out.println("Aan het starten, klaar om op te stijgen...");
}
public void superstarten(){
super.starten();
}
public void vliegen(){
System.out.println("Aan het vliegen...");
}
}
public class Wentelwiek extends Luchtvaartuig{
public Wentelwiek(){
System.out.println("Ik ben een Wentelwiek...");
}
public Wentelwiek(String s){
System.out.println("Stringconstructor Wentelwiek: " +s);
}
public void wentelen(){
System.out.println("Aan het wentelen...");
}
}
public class Jet extends Luchtvaartuig{
public Jet(){
System.out.println("Ik ben een Jet...");
}
public Jet(String s){
super(s);
System.out.println("Stringconstructor Jet: " +s);
}
public void zoeven(){
System.out.println("Aan het zoeven...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public Auto(String s){
super(s);
System.out.println("Stringconstructor Auto: " +s);
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Vervoermiddel a = new Auto("Vroem...");
a.starten();
//a.rijden();
System.out.println("");
System.out.println("Jet aan het maken...");
Jet j = new Jet("Zoef !!");
j.superstarten();
j.vliegen();
j.zoeven();
}
}
...
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Vervoermiddel a = new Auto("Vroem...");
a.starten();
//a.rijden();
...
}
}
Uitvoer: (met betrekking tot de Auto)
Auto aan het maken...
Stringconstructor Vervoermiddel: Vroem...
Stringconstructor Auto: Vroem...
Aan het starten...
a is nu een instantie van de klasse Vervoermiddel. a zal nu slechts toegang verlenen tot zijn eigen leden (variabelen, methoden).
Dit is interessant met het oog op het volgende punt: runtime-polymorfisme of dynamic method dispatch.
Runtime polymorfisme - Dynamic method dispatch
Een bijzondere kracht van Java is het ondersteunen van runtime-polymorfisme. Hiermee kan je een object runtime (terwijl het programma uitgevoerd wordt) verschillende gedaanten laten aannemen:
Toon volledige code...Toon nieuwe code...
public class Luchtvaartuig extends Vervoermiddel {
public Luchtvaartuig(){
System.out.println("Ik ben een luchtvaartuig...");
}
public Luchtvaartuig(String s){
super(s);
System.out.println("Stringconstructor Luchtvaartuig: " +s);
}
public void starten(){
System.out.println("Aan het starten, klaar om op te stijgen...");
}
public void superstarten(){
super.starten();
}
public void vliegen(){
System.out.println("Aan het vliegen...");
}
}
public class Wentelwiek extends Luchtvaartuig{
public Wentelwiek(){
System.out.println("Ik ben een Wentelwiek...");
}
public Wentelwiek(String s){
System.out.println("Stringconstructor Wentelwiek: " +s);
}
public void wentelen(){
System.out.println("Aan het wentelen...");
}
}
public class Jet extends Luchtvaartuig{
public Jet(){
System.out.println("Ik ben een Jet...");
}
public Jet(String s){
super(s);
System.out.println("Stringconstructor Jet: " +s);
}
public void zoeven(){
System.out.println("Aan het zoeven...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public Auto(String s){
super(s);
System.out.println("Stringconstructor Auto: " +s);
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...");
a.starten();
a.rijden();
System.out.println("");
System.out.println("Jet aan het maken...");
Jet j = new Jet("Zoef !!");
j.superstarten();
j.vliegen();
j.zoeven();
Wentelwiek w1 = new Wentelwiek();Jet j1 = new Jet ();Vervoermiddel v = new Vervoermiddel();v.starten();v = w1;v.starten();v = j1;v.starten();
}
}
...
public class Progvervoer {
public static void main(String[] args) {
...
Wentelwiek w1 = new Wentelwiek();Jet j1 = new Jet ();Vervoermiddel v = new Vervoermiddel();v.starten();v = w1;v.starten();v = j1;v.starten();
}
}
Uitvoer:
Ik ben een Vervoermiddel...
Ik ben een Luchtvaartuig...
Ik ben een Wentelwiek...
Ik ben een Vervoermiddel...
Ik ben een Luchtvaartuig...
Ik ben een Jet...
Ik ben een Vervoermiddel...
Aan het starten...
Aan het starten, klaar om op te stijgen...
Aan het starten, klaar om op te stijgen...
Zoals je merkt kan v als gedaante Vervoermiddel, Wentelwiek en Jet voorkomen. Methoden die vervangen werden in de nieuwe klasse worden op deze manier toegepast.
Abstracte klassen maken
We weten dat elk Vervoermiddel waarmee we willen rijden of vliegen uiteindelijk een Vervoermiddel is. Uiteindelijk zullen we dus alle Vervoermiddelen afleiden van de klasse Vervoermiddel. Wij wensen in feite geen objecten te maken van de klasse Vervoermiddel. Daarom kunnen we van de klasse Vervoermiddel een abstracte klasse maken: deze klasse vormt enkel een sjabloon voor het maken van nieuwe klassen. Elk type Vervoermiddel dat we gebruiken zal gepecifiëerd worden in een ander klasse.
We weten dat elk Vervoermiddel een methode starten moet hebben. Daarom kunnen we de methode starten in de klasse Vervoermiddel definiëren als abstracte methode: een klasse die afgeleid is van de klasse Vervoermiddel zal deze methode moeten implementeren. We leggen binnen de klasse Vervoermiddel dus niet vast hoe de methode moet worden uitgevoerd, wel dat ze in een subklasse moet aanwezig zijn.
De principes van abstracte klassen zijn in Java heel belangrijk daar een groot aantal methoden in de Java-pakketten zelf abstract zijn en dus vervangen moeten worden (denk aan de main-methode in een programma, de paint-methode in een applet,...).
We kunnen ons voorbeeld eenvoudig aanpassen naar dit nieuwe model, elke klasse afgeleid van de klasse Vervoermiddel moet nu wel de methode starten implementeren (subklassen van afgeleide klassen moet die natuurlijk niet nog een implementeren, maar het mag).
Toon volledige code...Toon nieuwe code...
public class Luchtvaartuig extends Vervoermiddel {
public Luchtvaartuig(){
System.out.println("Ik ben een luchtvaartuig...");
}
public Luchtvaartuig(String s){
super(s);
System.out.println("Stringconstructor Luchtvaartuig: " +s);
}
protected void starten(){
System.out.println("Aan het starten, klaar om op te stijgen...");
}
public void vliegen(){
System.out.println("Aan het vliegen...");
}
}
public class Wentelwiek extends Luchtvaartuig{
public Wentelwiek(){
System.out.println("Ik ben een Wentelwiek...");
}
public Wentelwiek(String s){
System.out.println("Stringconstructor Wentelwiek: " +s);
}
public void wentelen(){
System.out.println("Aan het wentelen...");
}
}
public class Jet extends Luchtvaartuig{
public Jet(){
System.out.println("Ik ben een Jet...");
}
public Jet(String s){
super(s);
System.out.println("Stringconstructor Jet: " +s);
}
public void zoeven(){
System.out.println("Aan het zoeven...");
}
}
abstract public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
abstract protected void starten();
}
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public Auto(String s){
super(s);
System.out.println("Stringconstructor Auto: " +s);
}
public void rijden(){
System.out.println("Aan het rijden...");
}
protected void starten() {
System.out.println("Aan het starten, klaar om te rijden...");
}
}
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...");
a.starten();
a.rijden();
System.out.println("");
System.out.println("Jet aan het maken...");
Jet j = new Jet("zoef !!");
j.starten();
j.vliegen();
j.zoeven();
System.out.println("");
}
}
...
public class Auto extends Vervoermiddel{
...
protected void starten() {
System.out.println("Aan het starten, klaar om te rijden...");
}
}
public class Luchtvaartuig extends Vervoermiddel {
...
protected void starten(){
System.out.println("Aan het starten, klaar om op te stijgen...");
}
...
}
...
abstract public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
abstract protected void starten();
}
...
Merk op dat ik de toegangsaanduider voor de abstracte methode starten in de klasse Vervoermiddel op protected heb gezet, en dat dus ook in de subklassen heb gedaan. Public zou natuurlijk ook werken. In de klasse Auto werd de methode starten aangemaakt, dit moet nu gebeuren, daar deze klasse afgeleid werd van de abstracte klasse Vervoermiddel, met de abstracte methode starten.
Interfaces
Interfaces vormen als het ware blauwdrukken voor de mogelijkheden (capabilities) die je kan gebruiken in klassen. In Interfaces leg je vast welke methoden een klasse die de interface implementeert moet hebben. In feite zal je dus bij het implementeren van een interface zeggen: een instantie van mijn klasse kan .... (invullen met de methodes uit de interface).
In een interface zal je dus methoden declareren, maar een geen concrete invulling aan geven.
In een klasse die de interface implementeert ben je dan verplicht die methoden van concrete opvulling te voorzien.
Voorbeelden hiervan zijn talrijk aanwezig bij de Listeners (afhandelen van muisklikken, toetsaanslagen,...) en dataverwerking.
In feite komt een interface neer op een abstracte klasse met enkel abstracte methoden (zie hierboven), het voordeel van een interface is dan echter dat een klasse die reeds een andere superklasse heeft de interface toch kan implementeren.
Een interface definiëert in feite de mogelijkheden (capabilities) van je klasse. Een interface implementeren in en klasse is nuttig daar je op die manier kan duidelijk maken over welke mogelijkheden de klasse zal beschikken.
Bij het zelf maken en implementeren van interfaces is het dus vooral een kwestie van duidelijkheid: je bent zeker dat een zelfde mogelijkheid (methode in een interface) in elke klasse die de interface implementeert dezelfde naam zal hebben, dit is heel interessant naar leesbaarheid en onderhoud van de code.
Bij eenvoudige programma's zal je wellicht vaak interfaces implementeren, maar zelf geen interfaces maken...
// deze klasse MijnPaneel is afgeleid van de klasse Jpanel
// (zie later, werken met Swing)
// en implementeert de interfaces ActionListener en MouseMotionListener
// Door implementatie van ActionListener moet de methode actionPerformed voorzien worden
// Door implementatie van MouseMotionListener moeten mouseDragged en mouseMoved voorzien worden.
public class MijnPaneel extends JPanel implements ActionListener, MouseMotionListener {
public void actionPerformed(ActionEvent e) {
/* methode-opdrachten */
}
public void mouseDragged(MouseEvent me) {
/* methode-opdrachten */
}
public void mouseMoved(MouseEvent me) {
/* methode-opdrachten */
}
// Andere code in deze klasse
}
Interfaces kan je zelf maken:
public interface MijnInterface{
public void methode1();
public void methode2(String s1);
}
static final constanten zijn toegestaan in een interface. (zie hieronder voor het begrip final)
final
Het woord final voor een klasse zorgt ervoor dat er geen subklassen van deze klasse kunnen worden afgeleid.
Het woord final voor een methode zorgt ervoor dat een methode niet meer kan worden overriden in een subklasse.
Het woord final voor een variabele zorgt ervoor dat de waarde van deze variabele niet meer kan worden aangepast. Het wordt een constante.
De principes van overerving nader bekeken
Nadat je alle leerstof in dit hoofdstuk grondig hebt doorgenomen kunnen we de principes die te maken hebben met overerving op volgende manier opvatten:
...is een...
Wanneer je kan zeggend dat een instantie van klasse b een instantie van klasse a is, dan ga je de klasse b afleiden van klasse a : class b extends a
In de voorbeeldtoepassing over de Vervoermiddelen:
Een Autois eenVervoermiddel
Een Luchtvaartuigis eenVervoermiddel
Een Wentelwiekis eenLuchtvaartuig
Een Jetis eenLuchtvaartuig
Toon volledige code...Toon nieuwe code...
public class Luchtvaartuig extends Vervoermiddel {
public Luchtvaartuig(){
System.out.println("Ik ben een luchtvaartuig...");
}
public Luchtvaartuig(String s){
super(s);
System.out.println("Stringconstructor Luchtvaartuig: " +s);
}
public void starten(){
System.out.println("Aan het starten, klaar om op te stijgen...");
}
public void vliegen(){
System.out.println("Aan het vliegen...");
}
}
public class Wentelwiek extends Luchtvaartuig{
public Wentelwiek(){
System.out.println("Ik ben een Wentelwiek...");
}
public Wentelwiek(String s){
System.out.println("Stringconstructor Wentelwiek: " +s);
}
public void wentelen(){
System.out.println("Aan het wentelen...");
}
}
public class Jet extends Luchtvaartuig{
public Jet(){
System.out.println("Ik ben een Jet...");
}
public Jet(String s){
super(s);
System.out.println("Stringconstructor Jet: " +s);
}
public void zoeven(){
System.out.println("Aan het zoeven...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public Auto(String s){
super(s);
System.out.println("Stringconstructor Auto: " +s);
}
public void rijden(){
System.out.println("Aan het rijden...");
}
}
public class Vervoermiddel {
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
protected void starten(){
System.out.println("Aan het starten...");
}
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...");
a.starten();
a.rijden();
System.out.println("");
System.out.println("Jet aan het maken...");
Jet j = new Jet("Zoef !!");
j.starten();
j.vliegen();
j.zoeven();
}
}
public class Luchtvaartuig extends Vervoermiddel {
...
}
public class Wentelwiek extends Luchtvaartuig{
...
}
public class Jet extends Luchtvaartuig{
...
}
public class Auto extends Vervoermiddel{
...
}
public class Vervoermiddel {
...
}
public class Progvervoer {
...
}
...heeft een...
We maken nog een klasse Motor voor onze toepassing.
De klasse Motor beschikt over de variabele soort, waarin de soortMotor kan worden bewaard.
De klasse Motor heeft een constructor waarbij een String wordt aangenomen en als soort wordt bewaard.
De klasse Motor beschikt ook nog over twee methoden toonSoort, die de gekozen soortMotor voor het huidige object toont en zetSoort waarmee je de soort van de Motor kan veranderen.
Elk Vervoermiddel uit onze toepassing heeft een Motor, We passen dan ook de klasse Vervoermiddel aan om dit te ondersteunen. We zorgen ervoor dat er een variabele motor van het type Motor als lid in onze klasse Vervoermiddel wordt opgenomen.
Daarnaast zorgen we er in de klasse Vervoermiddel voor dat er een nieuwe constructor aanwezezig is waarbij je bij het maken van een nieuwe instantie vervoermiddel een soortMotor kan meegeven.
We zorgen in de subklassen voor constructoren die de super instructie bevatten.
We kunnen hetvolgende besluiten:
Een Vervoermiddelheeft eenMotor
Auto's en Luchtvaartuigen zijn Vervoermiddelen, ze hebben dus een Motor
Wentelwieken en Jets zijn Luchtvaartuigen, ze hebben dus een Motor
Toon volledige code...Toon nieuwe code...
public class Motor {
private String soort;public Motor(String s) {
soort = s;
}
public String toonSoort(){
return soort;
}
public void zetSoort(String nieuwesoort){
soort = nieuwesoort;
}
}
public class Wentelwiek extends Luchtvaartuig{
public Wentelwiek(){
System.out.println("Ik ben een Wentelwiek...");
}
public Wentelwiek(String s){
System.out.println("Stringconstructor Wentelwiek: " +s);
}
public Wentelwiek(String s, String m){
super(s,m);
}
public void wentelen(){
System.out.println("Aan het wentelen...");
}
}
public class Jet extends Luchtvaartuig{
public Jet(){
System.out.println("Ik ben een Jet...");
}
public Jet(String s){
super(s);
System.out.println("Stringconstructor Jet: " +s);
}
public Jet(String s, String m){
super(s,m);
}
public void zoeven(){
System.out.println("Aan het zoeven...");
}
}
public class Luchtvaartuig extends Vervoermiddel {
public Luchtvaartuig(){
System.out.println("Ik ben een luchtvaartuig...");
}
public Luchtvaartuig(String s){
super(s);
System.out.println("Stringconstructor Luchtvaartuig: " +s);
}
public Luchtvaartuig(String s, String m){
super(s,m);
}
public void vliegen(){
System.out.println("Aan het vliegen...");
}
protected void starten(){
System.out.println("Aan het starten, klaar om op te stijgen...");
}
}
public class Auto extends Vervoermiddel{
public Auto() {
System.out.println("Ik ben een auto...");
}
public Auto(String s){
super(s);
System.out.println("Stringconstructor Auto: " +s);
}
public Auto(String s, String m){
super(s,m);
}
public void rijden(){
System.out.println("Aan het rijden...");
}
protected void starten() {
System.out.println("Aan het starten, klaar om te rijden...");
}
}
abstract public class Vervoermiddel {
protected Motor motor;
Vervoermiddel(){
System.out.println("Ik ben een vervoermiddel...");
}
Vervoermiddel(String s){
System.out.println("Stringconstructor Vervoermiddel: " +s);
}
Vervoermiddel(String s, String m){
motor = new Motor(m);System.out.println("Vervoermiddel: " +s +" Motor: " +m);
}
abstract protected void starten();
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...","Diesel");System.out.println("Type motor: " +a.motor.toonSoort()) ;
a.starten();
a.rijden();
System.out.println("Auto aan het maken...");
Auto b = new Auto("Tuuttuuut...","Benzine");
System.out.println("Type motor: " +b.motor.toonSoort()) ;
b.motor.zetSoort("LPG");
System.out.println("Nieuw motortype: " +b.motor.toonSoort());
b.starten();
b.rijden();
System.out.println("");
Jet j = new Jet("Zoef","Kerosine");
System.out.println("Type motor: " +j.motor.toonSoort());
j.starten();
j.vliegen();
j.zoeven();
}
}
public class Motor {
private String soort;public Motor(String s) {
soort = s;
}
public String toonSoort(){
return soort;
}
public void zetSoort(String nieuwesoort){
soort = nieuwesoort;
}
}
public class Wentelwiek extends Luchtvaartuig{
...
public Wentelwiek(String s, String m){
super(s,m);
}
...
}
public class Jet extends Luchtvaartuig{
...
public Jet(String s, String m){
super(s,m);
}
...
}
public class Luchtvaartuig extends Vervoermiddel {
...
public Luchtvaartuig(String s, String m){
super(s,m);
}
...
}
public class Auto extends Vervoermiddel{
...
public Auto(String s, String m){
super(s,m);
}
...
}
abstract public class Vervoermiddel {
protected Motor motor;
...
Vervoermiddel(String s, String m){
motor = new Motor(m);System.out.println("Vervoermiddel: " +s +" Motor: " +m);
}
abstract protected void starten();
}
public class Progvervoer {
public static void main(String[] args) {
System.out.println("Auto aan het maken...");
Auto a = new Auto("Vroem...","Diesel");System.out.println("Type motor: " +a.motor.toonSoort()) ;
a.starten();
a.rijden();
System.out.println("Auto aan het maken...");
Auto b = new Auto("Tuuttuuut...","Benzine");
System.out.println("Type motor: " +b.motor.toonSoort()) ;
b.motor.zetSoort("LPG");
System.out.println("Nieuw motortype: " +b.motor.toonSoort());
b.starten();
b.rijden();
System.out.println("");
Jet j = new Jet("Zoef","Kerosine");
System.out.println("Type motor: " +j.motor.toonSoort());
j.starten();
j.vliegen();
j.zoeven();
}
}
De klasse Vervoermiddel hoeft natuurlijk niet per se een abstracte klasse te zijn, daar er echter nooit objecten van de klasse Vervoermiddel moeten gemaakt worden was dat hier een goed idee.
...Kan...
Het gebruik van de relatie ...kan... is op te vatten op twee manieren:
...kan... als methode: een methode van een klasse definiëert wat de instanties van die klasse en afgeleide klassen zullen kunnen:
Een Vervoermiddelkanstarten
Een Autokan starten en rijden
Een Luchtvaartuigkanstarten en vliegen
Een Wentelwiekkanvliegen en wentelen
Een Jetkanvliegen en zoeven
Elk Vervoermiddel met een Motorkan de soortMotor tonen: toonSoort
Elke Vervoermiddel met een Motorkan de soortMotor instellen: zetSoort
...kan... als interface: wanneer je interfaces implementeert in een klasse zorg je ervoor dat je extra mogelijkheden (methodes) uit die interface kan gebruiken bij het implementeren van die methodes.
Een Applet kan muisklikken opvangen,... (interface ActionListener):
public class testApplet extends Applet implements ActionListener{
...
public void ActionPerformed(ActionEvent event){
...
}
...
}
De klasse Object
Elke klasse in Java is automatisch afgeleid van de klasse java.lang.Object, er is dus overerving betrokken bij alles wat je doet. Het belangrijkste hierbij is dat je weet dat elke klasse die je maakt al een aantal methoden kan gebruiken overgeërfd van de klasse java.lang.Object.
Met de getClass-methode kan je bijvoorbeeld voor elk object opvragen tot welke klasse het behoort.
Binnenklassen zijn niet-statische geneste klassen en zijn erg in trek uit overwegingen die te maken hebben met het afhandelen van gebeurtenissen. We zullen in de volgende hoofdstukken uitgebreid van die klassen gebruik maken.
Voorlopig leren we binnenklassen kennen aan de hand van een 'minder nuttig' voorbeeld.
public class A {
B b1;
public A() {
b1 = new B();
b1.print();
}
class B {
public void print(){
System.out.println("Binnen in B...");
}
}
}
public class Progbinnenklasse {
public static void main(String[] args) {
A a1 = new A();
}
}
In het hoofdprogramma maken we een instantie a1 van de klasse A.
De constructor van A zorgt ervoor dat nu een instantie b1 van de klasse B wordt aangemaakt en dat de methode print wordt aangeroepen.
Anonieme binnenklassen
Een afgekorte en populairder vorm van binnenklassen zijn anonieme binnenklassen. Een anonieme binnenklasse is een klasse die geen naam heeft en die je maakt met de volgende syntax:
new SuperType(constructor parameters){
//methoden en gegevens
}
In een abstract voorbeeld zien we hoe we een zin op het scherm brengen door gebruik te maken van een anonieme binnenklasse.
De binnenklasse heeft als SuperType de klasse Object (steeds aanwezig) en heeft één methode print die we meteen oproepen op volgende manier:
public class A {
public A()
{
( new Object() { public void print()
{
System.out.println("In anonieme binnenklasse...");
}
}
).print();
}
}
public class Progbinnenklasse {
public static void main(String[] args) {
A a1 = new A();
}
}