Polymorfisme in Java begrijpen: Concepten en Praktisch Gebruik
Wat is Polymorfisme?
Polymorfisme is de mogelijkheid van een object om veel vormen aan te nemen. Het meest voorkomende gebruik van polymorfisme in OOP treedt op wanneer een parent-klassereferentie wordt gebruikt om te verwijzen naar een child-klasseobject.
Elk Java-object dat meer dan één IS-A-test kan doorstaan, wordt als polymorf beschouwd. In Java zijn alle Java-objecten polymorf, omdat elk object de IS-A-test doorstaat voor hun eigen type en voor de klasse Object.
Het is belangrijk te weten dat de enige manier om toegang te krijgen tot een object is via een referentievariabele. Een referentievariabele kan maar één type hebben. Eenmaal gedeclareerd, kan het type van een referentievariabele niet worden gewijzigd.
De referentievariabele kan worden hertoegewezen aan andere objecten, mits deze niet final is gedeclareerd. Het type van de referentievariabele bepaalt welke methodes deze op het object kan aanroepen.
Een referentievariabele kan verwijzen naar elk object van het gedeclareerde type of elk subtype van het gedeclareerde type. Een referentievariabele kan worden gedeclareerd als een klasse- of interface-type.
Voorbeeld
public interface Vegetarian {}
public class Animal {}
public class Deer extends Animal implements Vegetarian {}
De Deer-klasse wordt als polymorf beschouwd omdat deze multiple inheritance heeft. De volgende stellingen zijn waar:
- Een Deer IS-EEN Animal
- Een Deer IS-EEN Vegetarian
- Een Deer IS-EEN Deer
- Een Deer IS-EEN Object
Als we de referentievariabele-feiten toepassen op een Deer-objectreferentie, zijn de volgende declaraties legaal:
Deer d = new Deer(); Animal a = d; Vegetarian v = d; Object o = d;
Alle referentievariabelen d, a, v, o verwijzen naar hetzelfde Deer-object in de heap.
Virtuele Methodes
In deze sectie laat ik zien hoe het gedrag van overschreven methodes in Java je in staat stelt om van polymorfisme gebruik te maken bij het ontwerpen van je klassen.
We hebben al method overriding besproken, waar een child-klasse een methode in zijn parent kan overschrijven. Een overschreven methode is essentieel verborgen in de parent-klasse, en wordt niet aangeroepen tenzij de child-klasse het super-sleutelwoord gebruikt binnen de overschrijvende methode.
Voorbeeld: Employee en Salary
/* Bestandsnaam: Employee.java */
public class Employee {
private String name;
private String address;
private int number;
public Employee(String name, String address, int number) {
System.out.println("Constructing an Employee");
this.name = name;
this.address = address;
this.number = number;
}
public void mailCheck() {
System.out.println("Mailing a check to " + this.name + " " + this.address);
}
public String toString() {
return name + " " + address + " " + number;
}
public String getName() { return name; }
public String getAddress() { return address; }
public void setAddress(String newAddress) { address = newAddress; }
public int getNumber() { return number; }
}
Nu breiden we Employee uit als volgt:
/* Bestandsnaam: Salary.java */
public class Salary extends Employee {
private double salary; // Jaarlijks salaris
public Salary(String name, String address, int number, double salary) {
super(name, address, number);
setSalary(salary);
}
public void mailCheck() {
System.out.println("Within mailCheck of Salary class ");
System.out.println("Mailing check to " + getName() + " with salary " + salary);
}
public double getSalary() { return salary; }
public void setSalary(double newSalary) {
if (newSalary >= 0.0) { salary = newSalary; }
}
public double computePay() {
System.out.println("Computing salary pay for " + getName());
return salary / 52;
}
}
Bestudeer het volgende programma en probeer de output te bepalen:
/* Bestandsnaam: VirtualDemo.java */
public class VirtualDemo {
public static void main(String[] args) {
Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00);
System.out.println("Call mailCheck using Salary reference --");
s.mailCheck();
System.out.println("\nCall mailCheck using Employee reference--");
e.mailCheck();
}
}
Resultaat:
Constructing an Employee Constructing an Employee Call mailCheck using Salary reference -- Within mailCheck of Salary class Mailing check to Mohd Mohtashim with salary 3600.0 Call mailCheck using Employee reference-- Within mailCheck of Salary class Mailing check to John Adams with salary 2400.0
Hier instantiëren we twee Salary-objecten. Één met een Salary-referentie s, en de ander met een Employee-referentie e.
Bij het aanroepen van s.mailCheck(), ziet de compiler mailCheck() in de Salary-klasse tijdens compilatie, en de JVM roept mailCheck() in de Salary-klasse aan tijdens runtime.
e.mailCheck() is heel anders omdat e een Employee-referentie is. Wanneer de compiler e.mailCheck() ziet, ziet de compiler de mailCheck()-methode in de Employee-klasse.
Tijdens compilatie gebruikte de compiler mailCheck() in Employee om deze statement te valideren. Tijdens runtime roept de JVM echter mailCheck() in de Salary-klasse aan.
Dit gedrag wordt aangeduid als virtuele methode-aanroep (virtual method invocation), en deze methodes worden virtuele methodes genoemd. Een overschreven methode wordt tijdens runtime aangeroepen, ongeacht welk datatype de referentie had die in de broncode tijdens compilatie werd gebruikt.
Java
- Java-operators beheersen: typen, syntax en praktische voorbeelden
- Java-commentaar: typen, gebruik en best practices
- Java Enhanced For-lus beheersen: syntax, voorbeelden en best practices
- Java Strings beheersen: aanmaken, methodes en best practices
- Java interfaces meesteren: concepten, implementatie en best practices
- Java anonieme inner classes meesteren: definitie, syntax en praktische voorbeelden
- Java Try-with-resources meesteren: automatische resource management uitgelegd
- Java Annotaties uitgelegd: typen, plaatsing en praktische voorbeelden
- Java Assertions: een praktische gids voor bugdetectie en codebetrouwbaarheid
- Java Vector begrijpen: Gebruik, Kenmerken en Vergelijking met ArrayList
- Polymorfisme in Java begrijpen: Concepten en Praktisch Gebruik