Explorer le polymorphisme basé sur l’héritage

Effectué

Le polymorphisme basé sur l’héritage repose sur une hiérarchie de classes dans laquelle les classes dérivées héritent du comportement et des propriétés d’une classe de base. La relation d’héritage vous permet de traiter les objets de classes dérivées en tant qu’objets de la classe de base. La possibilité de traiter des objets de classe dérivées en tant qu’objets de classe de base vous permet d’écrire du code qui fonctionne avec plusieurs types d’objets sans connaître le type spécifique lors de la compilation.

L’exemple de code suivant illustre le polymorphisme basé sur l’héritage en C# :


// Base class
public class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("The animal makes a sound.");
    }
}

// Derived class Dog
public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("The dog barks.");
    }
}

// Derived class Cat
public class Cat : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("The cat meows.");
    }
}

// Derived class Cow
public class Cow : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("The cow moos.");
    }
}

class Program
{
    static void Main()
    {
        // Create an array of Animal objects
        Animal[] animals = new Animal[3];

        Animal animal1 = new Dog();
        Animal animal2 = new Cat();
        Animal animal3 = new Cow();

        animals[0] = animal1;
        animals[1] = animal2;
        animals[2] = animal3;

        // Demonstrate polymorphism
        foreach (Animal animal in animals)
        {
            animal.MakeSound();
        }
    }
}

Dans cet exemple de code, vous remarquerez que la classe Program crée un tableau d’objets Animal et affecte des instances de Dog, Catet Cow aux éléments du tableau. La méthode MakeSound est appelée sur chaque objet du tableau, illustrant le polymorphisme. La méthode MakeSound est remplacée dans les classes dérivées pour fournir un comportement spécifique pour chaque type d’animal.

Cast d’un objet d’une classe de base en classe dérivée

Le transtypage en C# est le processus qui consiste à convertir un objet d’un type à un autre type. Le transtypage est souvent utilisé lors de la mise en œuvre du polymorphisme à l’aide de hiérarchies d’héritage, où vous disposez d’une classe de base et d’une ou plusieurs classes dérivées.

Il existe deux principaux types de transtypage :

  • Transtypage implicite : il se produit automatiquement lors de la conversion d’une classe dérivée en classe de base. Cette opération est sûre, car chaque instance d’une classe dérivée est également une instance de la classe de base.

    
    BankAccount account = new CheckingAccount();
    
    
  • Transtypage explicite : cela nécessite un opérateur de cast et est utilisé lors de la conversion d’une classe de base en une classe dérivée. Il n’est pas toujours sûr, car aucune instance d’une classe de base n’est une instance de la classe dérivée.

    
    CheckingAccount checkingAccount = (CheckingAccount)account;
    
    

Cast d’objets à l’aide des mots clés is et as

En C#, vous pouvez caster des objets à l’aide des mots clés is et as. Ces mots clés fournissent un moyen sûr de vérifier le type d’un objet avant de le passer en un autre type. Voici quelques façons courantes de convertir des objets en C# :

  • Utilisation du mot clé is avec des critères spéciaux :

    
    if (account is CheckingAccount checkingAccount)
    {
        // Use checkingAccount as a CheckingAccount
    }
    
    
    • Cette syntaxe vérifie si account est de type CheckingAccount.
    • Si la vérification réussit, elle convertit account en CheckingAccount et l’affecte à la variable checkingAccount.
    • Cette approche est concise et sûre, car elle combine la vérification de type et la conversion en une seule étape.
  • Utilisation du mot clé is suivi d’un transtypage explicite :

    
    if (account is CheckingAccount)
    {
        CheckingAccount checkingAccount = (CheckingAccount)account;
        // Use checkingAccount as a CheckingAccount
    }
    
    
    • Cette syntaxe vérifie si account est de type CheckingAccount.
    • Si la vérification réussit, elle convertit account en CheckingAccount et l’affecte à la variable checkingAccount.
    • Cette approche est plus détaillée que la syntaxe de critères spéciaux, mais fournit plus de contrôle sur le processus de transtypage.
  • Utilisation du mot clé as :

    
    CheckingAccount checkingAccount = account as CheckingAccount;
    
    if (checkingAccount != null)
    {
        // Use checkingAccount as a CheckingAccount
    }
    
    
    • Cette syntaxe tente de convertir account en CheckingAccount et affecte le résultat à checkingAccount.
    • Si le cast réussit, checkingAccount contient l’objet cast ; sinon, il est null.
    • Cette approche est utile lorsque vous souhaitez vérifier le résultat de cast avant d’utiliser l’objet cast. Par exemple, lorsque vous souhaitez éviter les exceptions et bien gérer les cas d’échec.
  • Lors de la mise en œuvre du transtypage, tenez compte des directives suivantes :

    • Utilisation des critères spéciaux avec is : combine la vérification de type et le cast en une seule étape.
    • Utilisation du mot clé is avec cast explicite : sépare la vérification du type et le cast en deux étapes, ce qui permet de mieux contrôler le processus de transtypage.
    • Utilisation du mot clé as : tente de caster et gère l’échec correctement en renvoyant null.

La compréhension de ces techniques de cast est essentielle pour travailler avec le polymorphisme et l’héritage en C#.

Évitez les pièges courants lors de la mise en œuvre du polymorphisme

Lorsque votre objectif est le polymorphisme basé sur l’héritage, voici quelques éléments à éviter et certaines choses à garantir :

  • Évitez d’utiliser des classes et des méthodes scellées : les classes et méthodes scellées ne peuvent être ni héritées ni remplacées, ce qui limite la possibilité d’utiliser le polymorphisme. Si vous scellez une classe ou une méthode, vous empêchez une extension et une personnalisation supplémentaires. Par exemple :

    
    public sealed class BankAccount { } // This class can't be inherited
    
    
  • Évitez d’utiliser des méthodes statiques excessives. Les méthodes statiques appartiennent à la classe elle-même et non à une instance de la classe. Ils ne peuvent pas être remplacés, ce qui signifie qu’ils ne participent pas au polymorphisme.

    
    public static void PrintMessage() { } // This method can't be overridden
    
    
  • Évitez le couplage serré. Le couplage serré se produit lorsque les classes ou les composants d’un système dépendent fortement les uns des autres. Autrement dit, les modifications apportées à une classe peuvent avoir une incidence directe sur les autres classes, ce qui rend le système moins flexible et plus difficile à maintenir. Un couplage serré peut entraîner des difficultés lors des tests, de l’extension et de la modification du code.

    
    public class BankAccount
    {
        public void TransferFunds(SavingsAccount savingsAccount)
        {
            // Tight coupling with SavingsAccount
        }
    }
    
    
  • Évitez d’utiliser le mot-clé « nouveau » sans raison valable. Le mot-clé « nouveau » masque la méthode de la classe de base dans la classe dérivée, ce qui peut entraîner une confusion et un comportement inattendu. Utilisez uniquement le mot clé « nouveau » lorsque vous envisagez de masquer intentionnellement la méthode de classe de base.

    
    public class Dog : Animal
    {
        public new void MakeSound() // Hides the base class method. Better to use 'override'
        {
            Console.WriteLine("The dog barks.");
        }
    }
    
    
  • Vérifiez les signatures de méthode cohérentes. Assurez-vous que les méthodes remplacées dans les classes dérivées ont la même signature que la méthode de la classe de base. La modification de la signature de la méthode entraînera le masquage de la méthode plutôt que son remplacement.

    
    public class Animal
    {
        public virtual void MakeSound(string sound)
        {
            Console.WriteLine("The animal makes a sound.");
        }
    }
    
    public class Dog : Animal
    {
        // Method signature doesn't match the base class
        public override void MakeSound()
        {
            Console.WriteLine("The dog barks.");
        }
    }
    
    

Résumé

Le polymorphisme basé sur l’héritage en C# vous permet de créer une hiérarchie de classes dans laquelle les classes dérivées héritent du comportement et des propriétés d’une classe de base. Ce mécanisme d’héritage vous permet de traiter les objets des classes dérivées comme des objets de la classe de base. La possibilité de traiter les objets de classes dérivées comme des membres d’une classe de base vous permet d’écrire du code qui fonctionne avec plusieurs types d’objets sans connaître le type spécifique lors de la compilation. Si vous comprenez les techniques de transtypage, évitez les pièges courants et suivez les meilleures pratiques, vous pouvez mettre en œuvre efficacement le polymorphisme dans vos applications C#.