Leçons du module (2/2)
Polymorphisme et Classes Abstraites
Le polymorphisme et les classes abstraites sont des concepts avancés de la programmation orientée objet qui permettent d'écrire du code flexible, extensible et indépendant des implémentations spécifiques.
Le Polymorphisme
Le terme polymorphisme (plusieurs formes) fait référence à la capacité de traiter des objets de différentes classes comme s'ils appartenaient à un type commun. En Java, une variable de type superclasse peut stocker une référence à un objet de n'importe quelle sous-classe.
class Animal {
public void makeSound() {
System.out.println("Verso...");
}
}
class Dog extends Animal {
public void makeSound() {
System.out.println("Woof");
}
}
class Cat extends Animal {
public void makeSound() {
System.out.println("Miao");
}
}
Grâce au polymorphisme, nous pouvons faire ceci :
Animal myAnimal1 = new Dog(); // Polimorfismo
Animal myAnimal2 = new Cat(); // Polimorfismo
myAnimal1.makeSound(); // Esegue il metodo di Dog (Woof)
myAnimal2.makeSound(); // Esegue il metodo di Cat (Miao)
La décision de quelle méthode invoquer se fait au moment de l'exécution (Late Binding ou dynamic dispatch) en fonction de l'objet réel et non du type de la variable de référence.
Classes Abstraites (abstract)
Une classe abstraite est une classe marquée du mot-clé abstract qui ne peut pas être instanciée directement (vous ne pouvez pas faire new MyAbstractClass()). Elle sert de "modèle partiel" pour d'autres classes.
Méthodes Abstraites
Une classe abstraite peut contenir des méthodes abstraites : des méthodes déclarées sans corps (sans accolades et sans code), se terminant par un point-virgule. Les sous-classes non abstraites sont obligées d'implémenter toutes les méthodes abstraites héritées.
abstract class Shape {
String color;
// Metodo astratto (senza corpo)
public abstract double getArea();
}
class Circle extends Shape {
double radius;
public Circle(double radius) {
this.radius = radius;
}
// Obbligatorio implementare getArea
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}
Dynamic Binding / Late Binding
Comment Java sait-il quelle méthode exécuter au moment de l'exécution ? Ce processus est connu sous le nom de Late Binding (ou Dynamic Binding). Contrairement à la surcharge (résolue au moment de la compilation), le compilateur ne sait pas quelle méthode spécifique sera exécutée. À la place, il génère une instruction d'appel générique. Au moment de l'exécution, la Java Virtual Machine (JVM) examine l'objet réel en mémoire et invoque l'implémentation de la méthode définie dans la classe de cet objet.
Classes Abstraites et Absence d'Implémentation
Si une sous-classe hérite d'une classe abstraite, elle a deux options :
- Implémenter toutes les méthodes abstraites : dans ce cas, la classe peut être une classe normale (concrète) et être instanciée.
- Se déclarer abstraite : si la sous-classe ne fournit pas d'implémentation pour toutes les méthodes abstraites héritées, elle doit à son tour être déclarée avec le mot-clé
abstract.
abstract class Animal {
public abstract void makeSound();
}
// Questa classe DEVE essere astratta perché non implementa makeSound()
abstract class Canine extends Animal {
// Eredita makeSound() ma non lo implementa
}
À toi de jouer
Déclarez une variable s de type Shape et attribuez-lui un nouvel objet Circle en utilisant le polymorphisme.
Afficher l'indice
Écrivez `Shape s = new Circle();` pour utiliser le type de base comme type de référence.
Solution disponible après 3 tentatives
Rendez la classe Shape abstraite et ajoutez la méthode abstraite double getArea(). Complétez ensuite Square pour qu'elle étende Shape et implémente getArea() en retournant side * side.
Afficher l'indice
Déclarez `public abstract double getArea();` dans Shape. Dans Square, ajoutez `@Override public double getArea() { return side * side; }`.
Solution disponible après 3 tentatives
Déclarez dans le main un tableau de type Shape[] contenant un objet Circle avec un rayon de 2.0 et un objet Square avec un côté de 3.0. Ensuite, utilisez une boucle (for ou for-each) pour afficher dans la console l'aire de chaque forme en appelant la méthode getArea().
Afficher l'indice
Déclarez le tableau avec `Shape[] shapes = { new Circle(2.0), new Square(3.0) };` et parcourez-le avec une boucle `for (Shape s : shapes)` en affichant `s.getArea()`.
Solution disponible après 3 tentatives