Polymorphisme dans Dart
Polymorphisme dans Dart
Objectifs du cours
-
Dans ce cours, vous découvrirez le polymorphisme dans le langage de programmation Dart à l’aide d’exemples. Avant d’en apprendre davantage sur le polymorphisme dans Dart, vous devez avoir une compréhension de base d’héritage à Dart.
-
Comprendre le concept de polymorphisme en Dart.
Poly
signifie plusieurs etmorph
signifie formes .- Le polymorphisme est la capacité d’un objet à prendre plusieurs formes. En tant qu’humains, nous avons la capacité de prendre de nombreuses formes. Nous pouvons être un étudiant, un enseignant, un parent, un ami, etc.
- De même, en programmation orientée objet, le polymorphisme est la capacité d’un objet à prendre plusieurs formes.
- Le polymorphisme est un concept clé de la programmation orientée objet (POO) qui permet à un objet de prendre différentes formes ou comportements en fonction du contexte dans lequel il est utilisé. En Dart, le polymorphisme est réalisé grâce à l’héritage et à la substitution de méthodes.
- En Dart, le polymorphisme se réfère à la capacité d’un objet à prendre différentes formes. Cela peut se manifester à travers l’héritage et les interfaces.
- Pour mieux comprendre le polymorphisme dans Dart, examinons un exemple concret. Supposons que nous ayons une classe de base appelée Animal :
- Maintenant, nous allons créer deux sous-classes de Animal, à savoir Chien et Chat. Ces sous-classes hériteront de la classe Animal et pourront également redéfinir (ou substituer) la méthode faireDuBruit() selon leurs propres comportements :
- Maintenant, nous pouvons créer des instances de Chien et Chat et les utiliser de manière polymorphique en tant qu’objets de type Animal :
- Dans cet exemple, bien que les variables chien et chat soient déclarées comme des objets de type Animal, elles conservent leurs comportements spécifiques définis dans les sous-classes Chien et Chat. C’est ce qu’on appelle le polymorphisme, où un objet de type plus général peut se comporter de manière spécifique en fonction de sa sous-classe réelle.
- Le polymorphisme est utile car il permet de créer des interfaces génériques et flexibles, où différentes classes peuvent être utilisées de manière interchangeable, tant qu’elles héritent de la même classe de base ou implémentent la même interface.
- En résumé, le polymorphisme dans Dart est réalisé grâce à l’héritage et à la substitution de méthodes. Il permet à un objet de prendre différentes formes ou comportements en fonction du contexte dans lequel il est utilisé.
-
Exemple
-
Interprétation
- Dans le code Dart que vous avez fourni, la variable g est d’abord déclarée comme étant de type Graphique, puis son référentiel est modifié pour référencer successivement des instances des classes dérivées Cercle et Rectangle. Cette flexibilité est permise grâce à la compatibilité entre un type de classe de base et une référence de classe dérivée.
- Lorsque vous appelez la méthode identifie() sur la variable g, la liaison dynamique des méthodes est utilisée. Cela signifie que la méthode appelée dépend du type réel de l’objet auquel g fait référence à ce moment-là. Ainsi, lorsque g fait référence à une instance de la classe Graphique, la méthode identifie() de la classe Graphique est appelée. Lorsque g fait référence à une instance de la classe Cercle, la méthode identifie() de la classe Cercle est appelée, et de même pour la classe Rectangle.
- Cela démontre le polymorphisme, qui est l’un des concepts clés de la programmation orientée objet. Le polymorphisme permet à des objets de différentes classes de répondre de manière spécifique aux mêmes appels de méthode, en fonction de leur type réel.
- En résumé, grâce à l’utilisation des classes de base et dérivées, ainsi que la liaison dynamique des méthodes, vous pouvez manipuler des objets de différentes classes de manière polymorphique et obtenir un comportement spécifique à chaque classe lors de l’appel des méthodes.
-
Application
-
Énoncé
- Développer les classes suivantes :
- Entité : comportant les champs privés nom, prénom et date de naissance, un constructeur pour initialiser les données, et une méthode polymorphe Afficher pour afficher les données de chaque entité.
- Travailleur : étendant Entité, avec en plus un champ Salaire accompagné de sa propriété, un constructeur et la redéfinition de la méthode Afficher.
- Manager : étendant Travailleur, avec en plus un champ Service accompagné de sa propriété, un constructeur et la redéfinition de la méthode Afficher.
- PDG : étendant Manager, avec en plus un champ Société accompagné de sa propriété, un constructeur et la redéfinition de la méthode Afficher.
- Travail à accomplir:
- Composer les classes Entité, Travailleur, Manager et PDG.
- Élaborer un programme de test comportant un tableau de huit entités : cinq travailleurs, deux managers et un PDG (8 références de la classe Entité contenant 5 instances de Travailleur, 2 de Manager et 1 de PDG).
- Présenter l’ensemble des éléments du tableau en utilisant une boucle for.
- Présenter l’ensemble des éléments du tableau en utilisant une boucle foreach.
-
Solution
class Animal {
void faireDuBruit() {
print('L\'animal fait du bruit !');
}
}
class Chien extends Animal {
@override
void faireDuBruit() {
print('Le chien aboie !');
}
}
class Chat extends Animal {
@override
void faireDuBruit() {
print('Le chat miaule !');
}
}
void main() {
Animal animal = Animal();
Animal chien = Chien();
Animal chat = Chat();
animal.faireDuBruit(); // Affiche : L'animal fait du bruit !
chien.faireDuBruit(); // Affiche : Le chien aboie !
chat.faireDuBruit(); // Affiche : Le chat miaule !
}
class Graphique {
late int x; // Coordonnée x du centre de l'objet
late int y; // Coordonnée y du centre de l'objet
Graphique(int x, int y) {
this.x = x; // Assigner la coordonnée x passée en paramètre à la variable d'instance x
this.y = y; // Assigner la coordonnée y passée en paramètre à la variable d'instance y
}
void identifie() {
print("Je suis une forme géométrique"); // Afficher le message "Je suis une forme géométrique"
}
void affiche() {
identifie(); // Appeler la méthode identifie() pour afficher le type de forme géométrique
print("Le centre de l'objet se trouve dans : $x et $y"); // Afficher les coordonnées du centre de l'objet
}
double surface() {
return 0; // Retourner une surface nulle (0) par défaut
}
}
class Cercle extends Graphique {
late double rayon; // Rayon du cercle
Cercle(int x, int y, double r) : super(x, y) {
rayon = r; // Assigner le rayon passé en paramètre à la variable d'instance rayon
}
@override
void identifie() {
print("Je suis un cercle"); // Afficher le message "Je suis un cercle"
}
@override
double surface() {
return rayon * 2 * 3.14; // Calculer et retourner la surface du cercle en utilisant la formule : rayon * 2 * π (approximation de π avec la valeur 3.14)
}
}
class Rectangle extends Graphique {
late int longueur; // Longueur du rectangle
late int largeur; // Largeur du rectangle
Rectangle(int x, int y, int l1, int l2) : super(x, y) {
longueur = l1; // Assigner la longueur passée en paramètre à la variable d'instance longueur
largeur = l2; // Assigner la largeur passée en paramètre à la variable d'instance largeur
}
@override
double surface() {
return longueur * largeur.toDouble(); // Calculer et retourner la surface du rectangle en multipliant la longueur par la largeur
}
@override
void identifie() {
print("Je suis un rectangle"); // Afficher le message "Je suis un rectangle"
}
}
void main() {
Graphique g = Graphique(3, 7); // Créer une instance de la classe Graphique avec les coordonnées (3, 7)
g.identifie(); // Appeler la méthode identifie() de l'objet g pour afficher le type de forme géométrique
g = Cercle(4, 8, 10); // Créer une instance de la classe Cercle avec les coordonnées (4, 8) et un rayon de 10
g.identifie(); // Appeler la méthode identifie() de l'objet g pour afficher le type de forme géométrique
g = Rectangle(7, 9, 10, 3); // Créer une instance de la classe Rectangle avec les coordonnées (7, 9), une longueur de 10 et une largeur de 3
g.identifie(); // Appeler la méthode identifie() de l'objet g pour afficher le type de forme géométrique
}
Code Dart
class Entite {
String nom;
String prenom;
DateTime dateNaissance;
Entite(this.nom, this.prenom, this.dateNaissance);
void afficher() {
print('Nom: $nom, Prénom: $prenom, Date de naissance: $dateNaissance');
}
}
class Travailleur extends Entite {
double salaire;
Travailleur(String nom, String prenom, DateTime dateNaissance, this.salaire)
: super(nom, prenom, dateNaissance);
@override
void afficher() {
super.afficher();
print('Salaire: $salaire');
}
}
class Manager extends Travailleur {
String service;
Manager(String nom, String prenom, DateTime dateNaissance, double salaire, this.service)
: super(nom, prenom, dateNaissance, salaire);
@override
void afficher() {
super.afficher();
print('Service: $service');
}
}
class PDG extends Manager {
String societe;
PDG(String nom, String prenom, DateTime dateNaissance, double salaire, String service, this.societe)
: super(nom, prenom, dateNaissance, salaire, service);
@override
void afficher() {
super.afficher();
print('Société: $societe');
}
}
void main() {
List<Entite> entites = [
Travailleur('Travailleur 1', 'Prenom 1', DateTime(1990, 1, 1), 2000),
Travailleur('Travailleur 2', 'Prenom 2', DateTime(1995, 2, 2), 2500),
Travailleur('Travailleur 3', 'Prenom 3', DateTime(1992, 3, 3), 1800),
Travailleur('Travailleur 4', 'Prenom 4', DateTime(1997, 4, 4), 2200),
Travailleur('Travailleur 5', 'Prenom 5', DateTime(1993, 5, 5), 1900),
Manager('Manager 1', 'Prenom 6', DateTime(1980, 6, 6), 3000, 'Service 1'),
Manager('Manager 2', 'Prenom 7', DateTime(1985, 7, 7), 2800, 'Service 2'),
PDG('PDG', 'Prenom 8', DateTime(1975, 8, 8), 5000, 'Service 3', 'Société A'),
];
print('Affichage avec for:');
for (int i = 0; i < entites.length; i++) {
entites[i].afficher();
print('');
}
print('Affichage avec forEach:');
entites.forEach((entite) {
entite.afficher();
print('');
});
}