Mots-clés Virtual & Override
Fait partie de la section Programmation Orientée Objet du Journey C# de Coddy. Leçon 21 sur 70.
Lorsqu’une classe dérivée hérite d’une méthode, tu souhaites parfois modifier complètement le comportement de cette méthode. Les mots-clés virtual et override fonctionnent ensemble pour rendre cela possible de manière contrôlée.
Marquez une méthode comme virtual dans la classe de base pour indiquer que les classes dérivées peuvent remplacer son implémentation :
public class Animal
{
public virtual void Speak()
{
Console.WriteLine("Some sound");
}
}
public class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("Woof!");
}
}Le mot-clé override dans la classe dérivée indique au compilateur que vous remplacez intentionnellement la méthode de base. Sans virtual sur la méthode de base, vous ne pouvez pas utiliser override.
La véritable puissance apparaît lorsque tu utilises une référence de classe de base pour contenir un objet dérivé :
Animal myPet = new Dog();
myPet.Speak(); // Sortie : Woof!Même si myPet est déclaré comme Animal, C# appelle la version de Dog de Speak(). C’est ce qu’on appelle le polymorphisme à l’exécution : la méthode appelée dépend du type réel de l’objet, et non du type déclaré de la variable.
Tu peux toujours accéder à l’implémentation de base à l’aide de base.Speak() dans ta redéfinition si tu veux étendre le comportement plutôt que le remplacer complètement.
Défi
FacileConstruisons un système de notifications qui montre comment les classes dérivées peuvent entièrement remplacer le comportement de la classe de base à l’aide des mots-clés virtual et override, tout en illustrant la puissance du polymorphisme à l’exécution.
Tu vas créer trois fichiers pour organiser ton code :
Notification.cs: définis une classeNotificationdans l’espace de nomsAlerts. Cette classe de base représente une notification générique avec une propriétéMessage(chaîne de caractères) et un constructeur qui lui attribue une valeur. Ajoute une méthodevirtualappeléeSend()qui renvoie"Sending notification: {Message}".EmailNotification.cs: définis une classeEmailNotificationdans l’espace de nomsAlertsqui hérite deNotification. Ajoute une propriétéRecipient(chaîne de caractères) et un constructeur qui accepte à la fois le message et le destinataire (utilisebasepour transmettre le message). Redéfinis la méthodeSend()pour qu’elle renvoie"Emailing {Recipient}: {Message}".SmsNotification.cs: définis une classeSmsNotificationdans l’espace de nomsAlertsqui hérite également deNotification. Ajoute une propriétéPhoneNumber(chaîne de caractères) et un constructeur qui accepte à la fois le message et le numéro de téléphone. RedéfinisSend()pour qu’elle renvoie"SMS to {PhoneNumber}: {Message}".Program.cs: dans ton fichier principal, crée des instances des trois types de notification à l’aide des valeurs saisies. Montre ensuite le polymorphisme à l’exécution en stockant les trois instances dans des variables de typeNotificationet en appelantSend()sur chacune d’elles.
Tu recevras quatre entrées :
- Le message de notification
- L’adresse e-mail du destinataire
- Le numéro de téléphone pour les SMS
Affiche le résultat de l’appel à Send() pour chaque notification, stockée dans une référence de la classe de base :
{base notification Send() result}
{email notification Send() result}
{sms notification Send() result}Par exemple, si les entrées sont Meeting at 3pm, alice@email.com et 555-1234, la sortie devrait être :
Sending notification: Meeting at 3pm
Emailing alice@email.com: Meeting at 3pm
SMS to 555-1234: Meeting at 3pmRemarque que, même si les trois instances sont stockées dans des variables de type Notification, chacune appelle sa propre version redéfinie de Send(). Voilà le polymorphisme à l’exécution en action !
Essayez vous-même
using System;
using Alerts;
class Program
{
public static void Main(string[] args)
{
// Lire les entrées
string message = Console.ReadLine();
string email = Console.ReadLine();
string phone = Console.ReadLine();
// TODO: Créer des instances des trois types de notifications
// Les stocker dans des variables de type Notification pour illustrer le polymorphisme
// TODO: Créer une instance de la classe de base Notification
Notification baseNotification;
// TODO: Créer une instance de EmailNotification (stockée dans une variable de type Notification)
Notification emailNotification;
// TODO: Créer une instance de SmsNotification (stockée dans une variable de type Notification)
Notification smsNotification;
// TODO: Appeler Send() sur chacune et afficher les résultats
// Les méthodes redéfinies seront appelées grâce au polymorphisme à l’exécution
}
}
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