Upcasting & Downcasting
Fait partie de la section Programmation Orientée Objet du Journey C# de Coddy. Leçon 29 sur 70.
Lorsque vous travaillez avec des hiérarchies d’héritage, vous devez souvent convertir des types de base et des types dérivés. Le upcasting convertit un type dérivé en son type de base, tandis que le downcasting fait l’inverse.
La conversion vers une classe de base est implicite et toujours sûre, car il est garanti qu’une classe dérivée possède tout ce que possède la classe de base :
Dog myDog = new Dog();
Animal animal = myDog; // Upcasting - implicite, fonctionne toujoursLe downcasting nécessite une conversion explicite et peut échouer lors de l’exécution si l’objet n’est pas réellement du type vers lequel vous effectuez la conversion :
Animal animal = new Dog();
Dog dog = (Dog)animal; // Downcasting - fonctionne car c'est réellement un Dog
Animal cat = new Cat();
Dog wrong = (Dog)cat; // Lève une InvalidCastException !Pour effectuer un transtypage descendant en toute sécurité, utilisez le mot-clé is pour vérifier d’abord le type, ou utilisez as, qui renvoie null au lieu de lever une exception :
if (animal is Dog d)
{
d.Bark(); // Sûr - d n'est disponible que si la vérification réussit
}
Dog maybeDog = animal as Dog;
if (maybeDog != null)
{
maybeDog.Bark();
}L’approche de correspondance de modèle is est privilégiée en C# moderne, car elle combine la vérification de type et la conversion en une seule étape, ce qui rend votre code à la fois plus sûr et plus clair.
Défi
FacileConstruisons un système d’inspection de véhicules qui montre comment l’upcasting et le downcasting vous permettent de travailler de manière flexible avec des objets dans une hiérarchie d’héritage. Vous créerez différents types de véhicules et écrirez du code qui identifie et utilise en toute sécurité des types de véhicules spécifiques.
Vous organiserez votre code sur quatre fichiers :
Vehicle.cs: définissez une classe de baseVehicledans l’espace de nomsInspection. Chaque véhicule possède une propriétéLicensePlate(string) définie par l’intermédiaire d’un constructeur. Incluez une méthode appeléeGetBasicInfo()qui renvoie"Vehicle: {LicensePlate}".Car.cs: définissez une classeCardans l’espace de nomsInspectionqui hérite deVehicle. Les voitures possèdent une propriété supplémentaireNumberOfDoors(int). Le constructeur accepte à la fois la plaque d’immatriculation et le nombre de portes. Ajoutez une méthode appeléeHonk()qui renvoie"{LicensePlate} honks: Beep beep!".Motorcycle.cs: définissez une classeMotorcycledans l’espace de nomsInspectionqui hérite deVehicle. Les motos possèdent une propriétéHasSidecar(bool). Le constructeur accepte la plaque d’immatriculation et la présence ou non d’un side-car. Ajoutez une méthode appeléeRev()qui renvoie"{LicensePlate} revs: Vroom!".Program.cs: dans votre fichier principal, vous créerez des véhicules et vous vous exercerez à la fois à l’upcasting et au downcasting sécurisé. Créez uneCaret uneMotorcycleà l’aide de valeurs saisies, puis stockez-les toutes les deux dans un tableau de référencesVehicle(upcasting). Parcourez le tableau et, pour chaque véhicule, affichez ses informations de base. Utilisez ensuite le mot-cléisavec la reconnaissance de formes pour effectuer un downcasting sécurisé : s’il s’agit d’uneCar, appelezHonk(); s’il s’agit d’uneMotorcycle, appelezRev().
Vous recevrez quatre entrées :
- Plaque d’immatriculation de la voiture
- Nombre de portes
- Plaque d’immatriculation de la moto
- Présence d’un side-car (
trueoufalse)
Affichez la sortie dans ce format pour chaque véhicule du tableau :
{GetBasicInfo() result}
{Honk() or Rev() result based on actual type}Par exemple, si les entrées sont ABC-123, 4, XYZ-789 et false, la sortie doit être :
Vehicle: ABC-123
ABC-123 honks: Beep beep!
Vehicle: XYZ-789
XYZ-789 revs: Vroom!Remarquez que tous les véhicules sont stockés en tant que références Vehicle (upcasting), mais que vous pouvez découvrir en toute sécurité leurs véritables types et accéder à des méthodes spécifiques à leur type en utilisant la syntaxe de reconnaissance de formes is pour effectuer un downcasting !
Essayez vous-même
using System;
using Inspection;
class Program
{
public static void Main(string[] args)
{
// Lire les entrées
string carPlate = Console.ReadLine();
int numberOfDoors = Convert.ToInt32(Console.ReadLine());
string motorcyclePlate = Console.ReadLine();
bool hasSidecar = Convert.ToBoolean(Console.ReadLine());
// TODO: Créer un objet Car en utilisant carPlate et numberOfDoors
// TODO: Créer un objet Motorcycle en utilisant motorcyclePlate et hasSidecar
// TODO: Créer un tableau de références Vehicle contenant les deux véhicules (upcasting)
// TODO: Parcourir le tableau et pour chaque véhicule :
// - Afficher le résultat de GetBasicInfo()
// - Utiliser le mot-clé 'is' avec le pattern matching pour effectuer un downcast sécurisé :
// - Si c'est une Car, appeler et afficher Honk()
// - Si c'est une Motorcycle, appeler et afficher Rev()
}
}
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 externesEspaces de noms et directivesIntro aux classes et objetsLe mot-clé 'this'Méthodes et paramètresChamps vs PropriétésConstructeursInitialiseurs d'objetsRécapitulatif - Calculatrice simple4Héritage
Syntaxe de base de l'héritage (:)Le mot-clé 'base'Mots-clés Virtual & OverrideClasses scelléesLa classe de base 'object'Récapitulatif - Hiérarchie des employés7Fonctionnalités avancées
Surcharge d'opérateursIndexeurs (this[])Redéfinition de ToString()Méthodes d'extensionRécapitulatif - Liste personnalisée10Patrons de conception - Partie 1
Introduction aux patrons de conceptionSingleton Thread-SafePatron FabriquePatron Observateur (Événements)Patron Stratégie2Propriétés et membres statiques
Propriétés auto-implémentéesPropriétés en lecture/écriture seuleChamps et méthodes statiquesClasses statiquesMembres à corps d'expression5Polymorphisme & Interfaces
Polymorphisme : Compilation vs ExécutionInterface vs Classe AbstraiteInterfaces MultiplesInterfaces ExplicitesUpcasting & DowncastingRécapitulatif - Calculateur de Formes8Concepts avancés de la POO
Composition plutôt qu'héritageGénériques (Classes et Méthodes)Délégués et ÉvénementsAttributs et RéflexionIDisposable et l'instruction usingBases de l'Injection de Dépendances11Patrons de conception, Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode TemplatePatron ÉtatPatron Composite3Architecture des classes
Données d'instance vs statiquesMots-clés 'readonly' & 'const'Champs de supportRécapitulatif - Gestionnaire de compte bancaire6Encapsulation
Modificateurs d'accèsPropriétés pour l'encapsulationImplémentation du masquage de donnéesPatterns d'immuabilitéRécapitulatif - Dossiers d'étudiants12Projet : Système de gestion de bibliothèque
Structure du projetModèles Livre et UtilisateurLogique du système d'empruntLINQ pour la rechercheInterface Console / Interface d'administrationTests unitaires (NUnit/xUnit)Entraînez-vous par vous-même : Compilateur C# en ligne