Java - Polymorphisme
Le polymorphisme est la capacité d'un objet à prendre de nombreuses formes. L'utilisation la plus courante du polymorphisme dans la POO se produit lorsqu'une référence de classe parent est utilisée pour faire référence à un objet de classe enfant.
Tout objet Java qui peut passer plus d'un test IS-A est considéré comme polymorphe. En Java, tous les objets Java sont polymorphes puisque tout objet passera le test IS-A pour son propre type et pour la classe Object.
Il est important de savoir que le seul moyen possible d'accéder à un objet est via une variable de référence. Une variable de référence ne peut être que d'un seul type. Une fois déclaré, le type d'une variable de référence ne peut pas être modifié.
La variable de référence peut être réaffectée à d'autres objets à condition qu'elle ne soit pas déclarée définitive. Le type de la variable de référence déterminerait les méthodes qu'elle peut invoquer sur l'objet.
Une variable de référence peut faire référence à tout objet de son type déclaré ou à tout sous-type de son type déclaré. Une variable de référence peut être déclarée en tant que type de classe ou d'interface.
Exemple
Prenons un exemple.
public interface Vegetarian{}
public class Animal{}
public class Deer extends Animal implements Vegetarian{}
Désormais, la classe Deer est considérée comme polymorphe car elle a un héritage multiple. Ce qui suit est vrai pour les exemples ci-dessus -
- Un cerf est-un animal
- Un cerf est-un végétarien
- Un cerf est-un cerf
- Un objet de cerf IS-A
Lorsque nous appliquons les faits de variable de référence à une référence d'objet Deer, les déclarations suivantes sont légales -
Exemple
Deer d = new Deer();
Animal a = d;
Vegetarian v = d;
Object o = d;
Toutes les variables de référence d, a, v, o font référence au même objet Deer dans le tas.
Méthodes virtuelles
Dans cette section, je vais vous montrer comment le comportement des méthodes surchargées en Java vous permet de tirer parti du polymorphisme lors de la conception de vos classes.
Nous avons déjà discuté du remplacement de méthode, où une classe enfant peut remplacer une méthode dans son parent. Une méthode remplacée est essentiellement masquée dans la classe parente et n'est appelée que si la classe enfant utilise le mot clé super dans la méthode de remplacement.
Exemple
/* File name : 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;
}
}
Supposons maintenant que nous étendions la classe Employee comme suit -
/* File name : Salary.java */
public class Salary extends Employee {
private double salary; // Annual salary
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;
}
}
Maintenant, vous étudiez attentivement le programme suivant et essayez de déterminer sa sortie -
/* File name : 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("\n Call mailCheck using Employee reference--");
e.mailCheck();
}
}
Cela produira le résultat suivant -
Production
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
Ici, nous instancions deux objets Salary. Un utilisant une référence de salaires, et l'autre utilisant une référence d'employé e.
Lors de l'appel de s.mailCheck () , le compilateur voit mailCheck () dans la classe Salary au moment de la compilation et la machine virtuelle Java appelle mailCheck () dans la classe Salary au moment de l'exécution.
mailCheck () sur e est assez différent parce que eest une référence d'employé. Lorsque le compilateur voit e.mailCheck () , le compilateur voit la méthode mailCheck () dans la classe Employee.
Ici, au moment de la compilation, le compilateur a utilisé mailCheck () dans Employee pour valider cette instruction. Au moment de l'exécution, cependant, la JVM appelle mailCheck () dans la classe Salary.
Ce comportement est appelé invocation de méthode virtuelle et ces méthodes sont appelées méthodes virtuelles. Une méthode remplacée est appelée au moment de l'exécution, quel que soit le type de données utilisé dans le code source au moment de la compilation.