Polymorfisme op basis van een interface verkennen

Voltooid

Met polymorfisme op basis van een interface kunt u een contract definiëren dat klassen moeten implementeren, zodat u polymorf gedrag kunt bereiken zonder te vertrouwen op de overname van klassen. Interfaces definiëren een set methoden en eigenschappen die een klasse moet implementeren, maar bieden geen implementatiedetails. Klassen kunnen meerdere interfaces implementeren, zodat ze gedrag kunnen definiëren voor verschillende aspecten van de toepassing.

Als u polymorfisme op basis van een interface wilt verkennen, kunt u beginnen met een scenario dat vergelijkbaar is met het op overname gebaseerde polymorfismescenario uit de vorige les.

Bekijk het volgende codevoorbeeld dat polymorfisme op basis van een interface in C# demonstreert:


// 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();
        }
    }
}

In dit codevoorbeeld wordt polymorfisme op basis van een interface gedemonstreerd door een ISound interface te definiëren die een MakeSound methode bevat. De klassen Dog, Caten Cow implementeren de ISound-interface door hun eigen implementaties van de MakeSound methode te bieden. De methode Main maakt een matrix van ISound objecten en wijst exemplaren van Dog, Caten Cow toe aan de matrix. De foreach lus doorloopt de matrix en roept de MakeSound methode voor elk object aan, waarbij polymorf gedrag wordt gedemonstreerd.

Op dit moment kan polymorfisme op basis van interface verwisselbaar zijn met op overname gebaseerde polymorfisme. Het bijwerken van de voorbeeldcode met het type toevoegingsklasse moet helpen om het verschil te demonstreren.

Bekijk het volgende bijgewerkte codevoorbeeld:


// 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();
        }
    }
}

Deze bijgewerkte voorbeeldcode bevat twee extra klassen, Doorbell en CarHorn, waarmee de ISound-interface wordt geïmplementeerd. Deze aanvullende klassen helpen om de meer flexibiliteit van polymorfisme op basis van een interface te demonstreren bij het definiëren van gedrag dat niet is gekoppeld aan een specifieke klassehiërarchie.

Polymorfisme op basis van een interface biedt extra voordelen, zoals het toestaan van klassen voor het implementeren van meerdere interfaces en het definiëren van contracten voor specifieke functionaliteit. Interfaces kunnen worden gebruikt om gemeenschappelijk gedrag te definiëren dat kan worden gedeeld in verschillende klassen, waardoor polymorfisme mogelijk is zonder dat er een gemeenschappelijke basisklasse nodig is.

Bekijk de volgende code waarmee objecten met één en meerdere interfaces worden gedemonstreert:


// 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();
    }
}

Vermijd veelvoorkomende valkuilen bij het implementeren van polymorfisme op basis van een interface

Wanneer uw doel is gebaseerd op polymorfisme op basis van een interface, zijn er enkele dingen die u moet vermijden en enkele dingen om ervoor te zorgen:

  • Vermijd het implementeren van niet-gerelateerde interfaces.
  • Vermijd standaard implementaties in interfaces. Hoewel C# standaard implementaties in interfaces toestaat, kan dit leiden tot verwarring en de duidelijkheid van het doel van de interface verminderen. Geef de voorkeur aan abstracte klassen voor gedeelde implementaties.
  • Vermijd overcomplicatie van interfacehiërarchieën. Houd interfacehiërarchieën eenvoudig en vermijd diepe overnameketens. Complexe hiërarchieën kunnen de code moeilijker begrijpen en onderhouden.
  • Zorg ervoor dat u het interfacescheidingsprincipe (ISP) volgt. De internetprovider geeft aan dat er geen client moet worden gedwongen om afhankelijk te zijn van methoden die niet worden gebruikt. Maak kleinere, specifiekere interfaces in plaats van één grote interface.

Samenvatting

Met polymorfisme op basis van interface kunt u contracten definiëren die moeten worden geïmplementeerd door klassen, zodat u polymorf gedrag kunt bereiken zonder afhankelijk te zijn van de overname van klassen. Door interfaces te implementeren, kunt u flexibele en onderhoudbare code maken die losse koppeling en hergebruik van code bevordert. Interfaces bieden een manier om gemeenschappelijk gedrag te definiëren dat kan worden gedeeld in verschillende klassen, zodat u met objecten van verschillende typen kunt werken via een gemeenschappelijke interface. Door inzicht te krijgen in polymorfisme op basis van een interface, kunt u modulaire en uitbreidbare toepassingen ontwerpen die na verloop van tijd gemakkelijker te onderhouden en ontwikkelen zijn.