Upcasting et Downcasting
Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy. Leçon 30 sur 87.
Dans la leçon précédente, tu as vu comment une variable de type parent peut contenir un objet enfant : Animal myPet = new Dog(). Cette affectation est appelée conversion ascendante (upcasting), et elle se produit automatiquement parce qu’un Dog est toujours un Animal.
La conversion ascendante remonte dans la hiérarchie d’héritage. Elle est implicite et toujours sûre :
Dog dog = new Dog();
Animal animal = dog; // Upcasting - automatiqueLorsque vous effectuez une conversion ascendante, vous ne pouvez accéder qu’aux méthodes définies dans la classe parente. Les méthodes propres à la classe enfant deviennent masquées, même si l’objet est toujours un Dog sous-jacent.
La conversion descendante va dans la direction opposée, en reconvertissant une référence au parent en un type enfant. Cela nécessite une conversion explicite, car ce n’est pas toujours sûr :
Animal animal = new Dog(); // Upcasting
Dog dog = (Dog) animal; // Downcasting - cast explicite requis
dog.bark(); // Maintenant nous pouvons accéder aux méthodes de DogLa conversion vers un type plus spécifique est risquée. Si l’objet n’est pas réellement du type vers lequel vous effectuez la conversion, Java lève une ClassCastException lors de l’exécution :
Animal animal = new Cat();
Dog dog = (Dog) animal; // Compile, mais plante à l'exécution !Le compilateur ne peut pas détecter cette erreur, car il ne voit que les types déclarés. Le type réel de l’objet n’est connu qu’au moment de l’exécution du programme. Dans la prochaine leçon, tu apprendras à vérifier en toute sécurité le type d’un objet avant d’effectuer une conversion descendante.
Défi
FacileConstruisons un système de lecteur multimédia qui démontre à la fois le upcasting et le downcasting en action. Tu vas créer une hiérarchie de types multimédias et t’exercer à effectuer des conversions entre des références parentes et enfants.
Tu organiseras ton code sur quatre fichiers :
Media.java: crée la classe de base que tous les types multimédias partagent. Chaque élément multimédia possède un champtitle(String). Inclus un constructeur pour l’initialiser, une méthode d’accèsgetTitle()et une méthodeplay()qui affiche :Playing: [title]Song.java: crée une classe qui extends Media. Les chansons possèdent un champ supplémentaireartist(String). Utilisesuperpour l’initialisation du parent. Remplaceplay()pour afficher :Playing song: [title] by [artist]. Ajoute une méthodeshowArtist()qui affiche :Artist: [artist]Podcast.java: crée une autre classe qui extends Media. Les podcasts possèdent un champepisode(int). Remplaceplay()pour afficher :Playing podcast: [title] - Episode [episode]. Ajoute une méthodeshowEpisode()qui affiche :Episode: [episode]Main.java: démontre le upcasting et le downcasting avec tes types multimédias. Tu recevras quatre entrées : le titre d’une chanson, le nom de l’artiste, le titre d’un podcast et un numéro d’épisode.Commence par créer un Song et effectuer un upcasting vers une référence Media. Appelle
play()sur cette référence pour observer le polymorphisme à l’exécution.Ensuite, effectue un downcasting de cette référence Media vers un Song et appelle
showArtist()pour accéder à la méthode propre à l’enfant.Puis, crée un Podcast et effectue un upcasting vers une référence Media. Appelle
play()sur cette référence.Enfin, effectue un downcasting de cette référence Media vers un Podcast et appelle
showEpisode().
Tu recevras quatre entrées : le titre de la chanson (String), le nom de l’artiste (String), le titre du podcast (String) et le numéro d’épisode (int).
Ta sortie doit afficher quatre lignes : deux pour la chanson (sa sortie de lecture et les informations sur l’artiste) et deux pour le podcast (sa sortie de lecture et les informations sur l’épisode). Remarque que le upcasting te permet de traiter différents types multimédias de manière uniforme, tandis que le downcasting te permet d’accéder à leurs fonctionnalités propres !
Essayez vous-même
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Lire les entrées
String songTitle = scanner.nextLine();
String artistName = scanner.nextLine();
String podcastTitle = scanner.nextLine();
int episodeNumber = scanner.nextInt();
// TODO: Créer un Song et l'upcaster vers une référence Media
// TODO: Appeler play() sur la référence Media (démontre le polymorphisme)
// TODO: Downcaster la référence Media vers Song
// TODO: Appeler showArtist() sur la référence Song
// TODO: Créer un Podcast et l'upcaster vers une référence Media
// TODO: Appeler play() sur la référence Media
// TODO: Downcaster la référence Media vers Podcast
// TODO: Appeler showEpisode() sur la référence Podcast
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesChamps (Attributs)Méthode constructeurSurcharge de constructeurRécapitulatif - Calculatrice simple4Héritage
Héritage de base (extends)Le mot-clé superRedéfinition de méthode (@Override)Chaînage de constructeursLa classe ObjectHéritage simple et multiniveauPourquoi pas d'héritage multiple de classesRécapitulatif - Hiérarchie des employés7Méthodes spéciales et classe Object
Méthode toString()equals() et hashCode()Méthode clone()compareTo() et ComparableInterface ComparatorRécapitulatif - Tri personnalisé2Modificateurs d'accès et Encapsulation
Aperçu des niveaux d'accèsMéthodes Getter et SetterMasquage d'informationsLe mot-clé finalRécapitulatif - Gestionnaire de compte bancaire5Polymorphisme
Bases de la surcharge de méthodesRedéfinition de méthodes (Run-Time)Upcasting et DowncastingL'opérateur instanceofClasses et méthodes abstraitesRécapitulatif - Calculateur de formes8Concepts avancés de la POO
Composition vs HéritageAgrégation vs CompositionClasses internes, imbriquées et anonymesEnums et méthodes d'EnumRecords (Java 16+)Classes scellées (Java 17+)11Patrons de conception, partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron MonteurPatron ObservateurPatron Stratégie3Propriétés de classe et membres statiques
Variables d'instance vs variables statiquesMéthodes statiquesBlocs statiquesConstantes (static final)Récapitulatif - Compteur et utilitaire6Interfaces et Classes Abstraites
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesDefault et Static dans les InterfacesClasses Abstraites vs InterfacesInterfaces FonctionnellesRécapitulatif - Système de Paiement9La généricité
Introduction à la généricitéClasses génériquesMéthodes génériquesParamètres de type bornésWildcards (?, extends, super)Récapitulatif - Conteneur générique12Patrons de conception, partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Template MethodPatron ÉtatPatron CompositePatron ItérateurEntraînez-vous par vous-même : Compilateur Java en ligne