Explorer le polymorphisme basé sur l’interface

Effectué

Le polymorphisme basé sur l’interface vous permet de définir un contrat que les classes doivent implémenter, ce qui vous permet d’obtenir un comportement polymorphe sans compter sur l’héritage de classe. Les interfaces définissent un ensemble de méthodes et de propriétés qu’une classe doit implémenter, mais ne fournissent aucun détail d’implémentation. Les classes peuvent implémenter plusieurs interfaces, ce qui leur permet de définir le comportement pour différents aspects de l’application.

Pour explorer le polymorphisme basé sur l’interface, vous pouvez commencer par un scénario similaire au scénario de polymorphisme basé sur l’héritage de l’unité précédente.

Considérez l’exemple de code suivant qui illustre le polymorphisme basé sur l’interface en C# :


// Define an interface
public interface ISound
{
    void MakeSound();
}

// Implement the interface in different classes
public class Dog : ISound
{
    public void MakeSound()
    {
        Console.WriteLine("The dog barks.");
    }
}

public class Cat : ISound
{
    public void MakeSound()
    {
        Console.WriteLine("The cat meows.");
    }
}

public class Cow : ISound
{
    public void MakeSound()
    {
        Console.WriteLine("The cow moos.");
    }
}

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

        ISound object1 = new Dog();
        ISound object2 = new Cat();
        ISound object3 = new Cow();

        myObjects[0] = object1;
        myObjects[1] = object2;
        myObjects[2] = object3;

        // Demonstrate polymorphism
        foreach (ISound currentObject in myObjects)
        {
            currentObject.MakeSound();
        }
    }
}

Dans cet exemple de code, le polymorphisme basé sur l’interface est démontré en définissant une interface ISound qui inclut une méthode MakeSound. Les classes Dog, Catet Cow implémentent l’interface ISound en fournissant leurs propres implémentations de la méthode MakeSound. La méthode Main crée un tableau d’objets ISound et affecte des instances de Dog, Catet Cow au tableau. La boucle foreach itère sur le tableau et appelle la méthode MakeSound sur chaque objet, illustrant le comportement polymorphe.

À ce stade, le polymorphisme basé sur l’interface peut apparaître interchangeable avec le polymorphisme basé sur l’héritage. La mise à jour de l’exemple de code avec un type de classe d’ajout doit vous aider à illustrer la différence.

Tenez compte de l’exemple de code mis à jour suivant :


// Define an interface
public interface ISound
{
    void MakeSound();
}

// Implement the interface in different classes
public class Dog : ISound
{
    public void MakeSound()
    {
        Console.WriteLine("The dog barks.");
    }
}

public class Cat : ISound
{
    public void MakeSound()
    {
        Console.WriteLine("The cat meows.");
    }
}

public class Cow : ISound
{
    public void MakeSound()
    {
        Console.WriteLine("The cow moos.");
    }
}

public class Doorbell : ISound
{
    public void MakeSound()
    {
        Console.WriteLine("The doorbell rings.");
    }
}

public class CarHorn : ISound
{
    public void MakeSound()
    {
        Console.WriteLine("The car horn honks.");
    }
}

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

        ISound object1 = new Dog();
        ISound object2 = new Cat();
        ISound object3 = new Cow();
        ISound object4 = new Doorbell();
        ISound object5 = new CarHorn();

        myObjects[0] = object1;
        myObjects[1] = object2;
        myObjects[2] = object3;
        myObjects[3] = object4;
        myObjects[4] = object5;

        // Demonstrate polymorphism
        foreach (ISound currentObject in myObjects)
        {
            currentObject.MakeSound();
        }
    }
}

Cet exemple de code mis à jour comprend deux classes supplémentaires, Doorbell et CarHorn, qui implémentent l’interface ISound. Ces classes supplémentaires aident à illustrer la flexibilité accrue du polymorphisme basé sur l’interface pour définir le comportement qui n’est pas lié à une hiérarchie de classes spécifique.

Le polymorphisme basé sur l’interface offre des avantages supplémentaires, tels que la possibilité de permettre aux classes d’implémenter plusieurs interfaces et de définir des contrats pour des fonctionnalités spécifiques. Les interfaces peuvent être utilisées pour définir un comportement commun qui peut être partagé entre différentes classes, ce qui permet la polymorphisme sans avoir besoin d’une classe de base commune.

Considérez le code suivant qui illustre les objets avec une seule et plusieurs interfaces :


// Define an interface for sound
public interface ISound
{
    void MakeSound();
}

// Define an interface for movement
public interface IMovable
{
    void Move();
}

// Implement the ISound and IMovable interfaces in different classes
public class Dog : ISound, IMovable
{
    public void MakeSound()
    {
        Console.WriteLine("The dog barks.");
    }

    public void Move()
    {
        Console.WriteLine("The dog runs.");
    }
}

public class Cat : ISound, IMovable
{
    public void MakeSound()
    {
        Console.WriteLine("The cat meows.");
    }

    public void Move()
    {
        Console.WriteLine("The cat jumps.");
    }
}

public class Cow : ISound, IMovable
{
    public void MakeSound()
    {
        Console.WriteLine("The cow moos.");
    }

    public void Move()
    {
        Console.WriteLine("The cow walks.");
    }
}

public class Doorbell : ISound
{
    public void MakeSound()
    {
        Console.WriteLine("The doorbell rings.");
    }
}

public class CarHorn : ISound
{
    public void MakeSound()
    {
        Console.WriteLine("The car horn honks.");
    }
}

class Program
{
    static void Main()
    {
        // Create an array of ISound objects
        ISound[] soundObjects = new ISound[5];

        ISound object1 = new Dog();
        ISound object2 = new Cat();
        ISound object3 = new Cow();
        ISound object4 = new Doorbell();
        ISound object5 = new CarHorn();

        soundObjects[0] = object1;
        soundObjects[1] = object2;
        soundObjects[2] = object3;
        soundObjects[3] = object4;
        soundObjects[4] = object5;

        // Demonstrate polymorphism with ISound
        Console.WriteLine("Demonstrating ISound polymorphism:");
        foreach (ISound currentObject in soundObjects)
        {
            currentObject.MakeSound();
        }

        // Create an array of IMovable objects
        IMovable[] movableObjects = new IMovable[3];

        IMovable movableObject1 = new Dog();
        IMovable movableObject2 = new Cat();
        IMovable movableObject3 = new Cow();

        movableObjects[0] = movableObject1;
        movableObjects[1] = movableObject2;
        movableObjects[2] = movableObject3;

        // Demonstrate polymorphism with IMovable
        Console.WriteLine("\nDemonstrating IMovable polymorphism:");
        foreach (IMovable currentObject in movableObjects)
        {
            currentObject.Move();
        }

        // Demonstrate objects with single and multiple interfaces
        Console.WriteLine("\nDemonstrating objects with single and multiple interfaces:");
        Dog dog = new Dog();
        Cat cat = new Cat();
        Cow cow = new Cow();
        Doorbell doorbell = new Doorbell();
        CarHorn carHorn = new CarHorn();

        dog.MakeSound();
        dog.Move();

        cat.MakeSound();
        cat.Move();

        cow.MakeSound();
        cow.Move();

        doorbell.MakeSound();

        carHorn.MakeSound();
    }
}

Évitez les pièges courants lors de l’implémentation du polymorphisme basé sur l’interface

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

  • Évitez d’implémenter des interfaces non liées.
  • Évitez les implémentations par défaut dans les interfaces. Bien que C# autorise les implémentations par défaut dans les interfaces, cela peut entraîner une confusion et réduire la clarté de l’objectif de l’interface. Préférer les classes abstraites pour les implémentations partagées.
  • Évitez de surcompliquer les hiérarchies d’interface. Conservez les hiérarchies d’interface simples et évitez les chaînes d’héritage profondes. Les hiérarchies complexes peuvent rendre le code plus difficile à comprendre et à gérer.
  • Vérifiez que vous suivez le principe de séparation d’interface (ISP). L’ISP indique qu’aucun client ne doit être obligé de dépendre des méthodes qu’il n’utilise pas. Créez des interfaces plus petites et plus spécifiques plutôt qu’une seule interface volumineuse.

Résumé

Le polymorphisme basé sur l’interface vous permet de définir des contrats que les classes doivent implémenter, ce qui vous permet d’obtenir un comportement polymorphe sans compter sur l’héritage de classe. En implémentant des interfaces, vous pouvez créer du code flexible et gérable qui favorise le couplage libre et la réutilisabilité du code. Les interfaces permettent de définir un comportement commun qui peut être partagé entre différentes classes, ce qui vous permet d’utiliser des objets de différents types via une interface commune. En comprenant le polymorphisme basé sur l’interface, vous pouvez concevoir des applications modulaires et extensibles qui sont plus faciles à gérer et à évoluer au fil du temps.