Polymorphisme Java


Le polymorphisme est la capacité d'un même comportement à avoir plusieurs formes ou manifestations différentes.

Le polymorphisme est la même interface, utilisant différentes instances pour effectuer différentes opérations, comme le montre la figure :

Le polymorphisme est la manifestation d'objets sous plusieurs formes.

Dans la vie réelle, par exemple, l'action d'appuyer sur la touche F1 :

  • Si vous êtes actuellement dans l'interface Flash, la documentation d'aide AS 3 s'affiche ;
  • Si vous êtes actuellement dans Word, l'aide de Word s'affiche ;
  • Sous Windows, l'aide et le support Windows s'affichent.

Le même événement se produisant sur des objets différents produit des résultats différents.

Avantages du polymorphisme

  • 1. Éliminer les relations de couplage entre les types
  • 2. Remplaçabilité
  • 3. Extensibilité
  • 4. Capacité d'interfaçage
  • 5. Flexibilité
  • 6. Simplification

Trois conditions nécessaires au polymorphisme

  • Héritage
  • Redéfinition
  • Une référence de classe parente pointe vers un objet de sous-classe :Parent p = new Child();

class Shape {
    void draw() {}
}
 
class Circle extends Shape {
    void draw() {
        System.out.println("Circle.draw()");
    }
}
 
class Square extends Shape {
    void draw() {
        System.out.println("Square.draw()");
    }
}
 
class Triangle extends Shape {
    void draw() {
        System.out.println("Triangle.draw()");
    }
}

Lors de l'appel d'une méthode en utilisant le polymorphisme, vérifiez d'abord si la classe parente possède cette méthode. Si ce n'est pas le cas, une erreur de compilation se produit ; si oui, appelez la méthode de la sous-classe portant le même nom.

Avantage du polymorphisme : il peut donner aux programmes une bonne extensibilité et permettre de gérer génériquement tous les objets de classe.

Ce qui suit est une démonstration d'un exemple de polymorphisme. Pour une explication détaillée, veuillez consulter les commentaires :

Code du fichier Test.java :

public class Test { public static void main(String[] args) { show(new Cat()); //Appeler la méthode show avec un objet Cat show(new Dog()); //Appeler la méthode show avec un objet Dog Animal a = new Cat(); //Conversion ascendante a.eat(); //Appelle eat de Cat Cat c = (Cat)a; //Conversion descendante c.work(); //Appelle work de Cat } public static void show(Animal a) { a.eat(); //Vérification de type if (a instanceof Cat) { //Ce que font les chats Cat c = (Cat)a; c.work(); } else if (a instanceof Dog) { //Ce que font les chiens Dog c = (Dog)a; c.work(); } } } abstract class Animal { abstract void eat(); } class Cat extends Animal { public void eat() { System.out.println("Manger du poisson"); } public void work() { System.out.println("Attraper des souris"); } } class Dog extends Animal { public void eat() { System.out.println("Manger des os"); } public void work() { System.out.println("Garder la maison"); } }

Exécutez le programme ci-dessus, le résultat de sortie est :

eat fish
catch mice
eat bones
guard the house
eat fish
catch mice

Fonctions virtuelles

Les fonctions virtuelles existent pour le polymorphisme.

Java n'a en fait pas le concept de fonctions virtuelles. Ses fonctions ordinaires sont équivalentes aux fonctions virtuelles de C++, et la liaison dynamique est le comportement par défaut en Java. Si vous ne voulez pas qu'une fonction ait les caractéristiques d'une fonction virtuelle en Java, vous pouvez ajouter le mot-clé final pour en faire une fonction non virtuelle.

Redéfinition

Nous allons présenter comment le comportement des méthodes redéfinies affecte le polymorphisme lors de la conception de classes en Java.

Nous avons déjà discuté de la redéfinition des méthodes, c'est-à-dire que les sous-classes peuvent redéfinir les méthodes de la classe parente.

Lorsqu'un objet de sous-classe appelle une méthode redéfinie, il appelle la méthode de la sous-classe, et non la méthode redéfinie de la classe parente.

Pour appeler la méthode redéfinie dans la classe parente, vous devez utiliser le mot-clésuper。

Code du fichier Employee.java :

/*Nom du fichier : 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("Constructeur Employee"); this.name = name; this.address = address; this.number = number; } public void mailCheck() { System.out.println("Envoi d'un chèque à :" + 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 que la classe suivante hérite de la classe Employee :

Code du fichier Salary.java :

/*Nom du fichier : Salary.java*/ public class Salary extends Employee { private double salary; //Salaire annuel public Salary(String name, String address, int number, double salary) { super(name, address, number); setSalary(salary); } public void mailCheck() { System.out.println("méthode mailCheck de la classe Salary"); System.out.println("Envoi d'un chèque à :" + getName() + ", salaire :" + salary); } public double getSalary() { return salary; } public void setSalary(double newSalary) { if(newSalary >= 0.0) { salary = newSalary; } } public double computePay() { System.out.println("Calculer la paie, payer à :" + getName()); return salary/52; } }

Maintenant, lisons attentivement le code suivant et essayons de donner son résultat de sortie :

Code du fichier VirtualDemo.java :

/*Nom du fichier : VirtualDemo.java*/ public class VirtualDemo { public static void main(String [] args) { Salary s = new Salary("Employé A", "Pékin", 3, 3600.00); Employee e = new Salary("Employé B", "Shanghai", 2, 2400.00); System.out.println("Appel de mailCheck en utilisant la référence Salary --"); s.mailCheck(); System.out.println("\nAppel de mailCheck en utilisant la référence Employee--"); e.mailCheck(); } }

Le résultat de compilation et d'exécution de l'exemple ci-dessus est le suivant :

Employee 构造函数
Employee 构造函数
使用 Salary 的引用调用 mailCheck -- 
Salary 类的 mailCheck 方法 
邮寄支票给:员工 A ,工资为:3600.0

使用 Employee 的引用调用 mailCheck--
Salary 类的 mailCheck 方法 
邮寄支票给:员工 B ,工资为:2400.0

Analyse de l'exemple

  • Dans l'exemple, deux objets Salary sont instanciés : l'un en utilisant la référence Salary s, et l'autre en utilisant la référence Employee e.

  • Lors de l'appel à s.mailCheck(), le compilateur trouve mailCheck() dans la classe Salary au moment de la compilation, et lors de l'exécution la JVM appelle le mailCheck() de la classe Salary.

  • e est une référence Employee, mais la référence e exécute finalement la méthode mailCheck() de la classe Salary.

  • Au moment de la compilation, le compilateur utilise la méthode mailCheck() de la classe Employee pour valider l'instruction, mais à l'exécution, la machine virtuelle Java (JVM) appelle la méthode mailCheck() de la classe Salary.

L'ensemble du processus ci-dessus est appelé invocation de méthode virtuelle, et la méthode est appelée méthode virtuelle.

Toutes les méthodes en Java peuvent se comporter de cette manière. Par conséquent, les méthodes redéfinies peuvent être appelées à l'exécution, quel que soit le type de données de la variable de référence dans le code source au moment de la compilation.


Façons de mettre en œuvre le polymorphisme

Méthode 1 : Redéfinition :

Ce contenu a déjà été traité en détail dans le chapitre précédent, donc aucune explication supplémentaire n'est donnée. Pour plus de détails, veuillez consulter :Redéfinition et surcharge en Java。

Méthode 2 : Interfaces

  • 1. L'interface la plus représentative dans la vie est une prise. Par exemple, une fiche à trois broches peut être insérée dans une prise à trois trous, car chaque pays a ses propres règles d'interface. Cela peut ne pas fonctionner à l'étranger, car les pays étrangers définissent leurs propres types d'interface.

  • 2. Une interface en Java est similaire à une interface dans la vie ; c'est une collection de signatures de méthodes, mais sans implémentations de méthodes. Pour plus de détails, voirInterfaces Javadans ce chapitre.

Méthode 3 : classes abstraites et méthodes abstraites

Pour plus de détails, voir le chapitreClasses abstraites Java.

Autres extensions