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, vous avez vu comment une variable de type parent peut contenir un objet enfant : Animal myPet = new Dog(). Cette affectation est appelée upcasting, et elle se produit automatiquement car un Dog est toujours un Animal.
L'upcasting remonte la hiérarchie d'héritage. C'est implicite et toujours sûr :
Dog dog = new Dog();
Animal animal = dog; // Upcasting - automatiqueLorsque vous effectuez un upcasting, vous ne pouvez accéder qu'aux méthodes définies dans la classe parente. Les méthodes spécifiques à la classe enfant deviennent masquées, même si l'objet est toujours un Dog en réalité.
Le downcasting s'effectue dans le sens inverse, en convertissant une référence parente en un type enfant. Cela nécessite un transtypage explicite car ce n'est pas toujours sûr :
Animal animal = new Dog(); // Upcasting
Dog dog = (Dog) animal; // Downcasting - transtypage explicite requis
dog.bark(); // Maintenant, nous pouvons accéder aux méthodes de DogLe transtypage descendant (downcasting) est risqué. Si l'objet n'est pas réellement du type vers lequel vous effectuez le transtypage, Java lève une ClassCastException à 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 que lors de l'exécution du programme. Dans la prochaine leçon, vous apprendrez comment vérifier en toute sécurité le type d'un objet avant d'effectuer un transtypage descendant (downcasting).
Défi
FacileConstruisons un système de lecteur multimédia qui démontre à la fois l'upcasting et le downcasting en action. Vous allez créer une hiérarchie de types de médias et vous entraîner à convertir entre les références parent et enfant.
Vous organiserez votre code sur quatre fichiers :
Media.java: Créez la classe de base que tous les types de médias partagent. Chaque élément multimédia possède un champtitle(String). Incluez un constructeur pour l'initialiser, une méthode gettergetTitle(), et une méthodeplay()qui affiche :"Playing: " + titleSong.java: Créez une classe qui étend Media. Les chansons ont un champ supplémentaireartist(String). Utilisezsuperpour l'initialisation du parent. Surchargezplay()pour afficher :"Playing song: " + title + " by " + artist. Ajoutez une méthodeshowArtist()qui affiche :"Artist: " + artistPodcast.java: Créez une autre classe qui étend Media. Les podcasts ont un champepisode(int). Surchargezplay()pour afficher :"Playing podcast: " + title + " - Episode " + episode. Ajoutez une méthodeshowEpisode()qui affiche :"Episode: " + episodeMain.java: Démontrez l'upcasting et le downcasting avec vos types de médias. Vous recevrez quatre entrées : un titre de chanson, un nom d'artiste, un titre de podcast et un numéro d'épisode.Tout d'abord, créez un Song et effectuez un upcasting vers une référence Media. Appelez
play()sur cette référence pour voir le polymorphisme au moment de l'exécution à l'œuvre.Ensuite, effectuez un downcasting de cette référence Media vers un Song et appelez
showArtist()pour accéder à la méthode spécifique à l'enfant.Ensuite, créez un Podcast et effectuez un upcasting vers une référence Media. Appelez
play()sur cette référence.Enfin, effectuez un downcasting de cette référence Media vers un Podcast et appelez
showEpisode().
Vous recevrez quatre entrées : le titre de la chanson (String), le nom de l'artiste (String), le titre du podcast (String) et le numéro de l'épisode (int).
Votre sortie devrait 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). Remarquez comment l'upcasting vous permet de traiter différents types de médias de manière uniforme, tandis que le downcasting vous permet d'accéder à leurs fonctionnalités uniques !
Aide-mémoire
En Java, le upcasting (transtypage ascendant) remonte la hiérarchie d'héritage et se produit automatiquement. Un objet enfant peut être assigné à une variable de type parent :
Dog dog = new Dog();
Animal animal = dog; // Upcasting - automatiqueLorsque vous effectuez un upcasting, vous ne pouvez accéder qu'aux méthodes définies dans la classe parente, même si l'objet est toujours du type enfant en réalité.
Downcasting (transtypage descendant) convertit une référence parente en un type enfant. Il nécessite un transtypage explicite :
Animal animal = new Dog(); // Upcasting
Dog dog = (Dog) animal; // Downcasting - transtypage explicite requis
dog.bark(); // Maintenant, nous pouvons accéder aux méthodes de DogLe downcasting est risqué. Si l'objet n'est pas réellement du type vers lequel vous effectuez le transtypage, Java lève une ClassCastException à 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 que lors de l'exécution du programme.
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 une chanson (Song) et effectuer un upcasting vers une référence Media
// TODO: Appeler play() sur la référence Media (démontre le polymorphisme)
// TODO: Effectuer un downcasting de la référence Media vers Song
// TODO: Appeler showArtist() sur la référence Song
// TODO: Créer un Podcast et effectuer un upcasting vers une référence Media
// TODO: Appeler play() sur la référence Media
// TODO: Effectuer un downcasting de 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érateur