Utforska arvsbaserad polymorfism

Fullbordad

Arvsbaserad polymorfism baseras på en klasshierarki där härledda klasser ärver beteende och egenskaper från en basklass. Med arvsrelationen kan du behandla objekt av härledda klasser som objekt i basklassen. Genom att kunna behandla härledda klassobjekt som basklassobjekt kan du skriva kod som fungerar med flera typer av objekt utan att känna till den specifika typen vid kompileringstiden.

Följande kodexempel visar arvsbaserad polymorfism i 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();
        }
    }
}

I den här exempelkoden ser du att klassen Program skapar en matris med Animal objekt och tilldelar instanser av Dog, Catoch Cow till matriselementen. Metoden MakeSound anropas för varje objekt i matrisen, vilket visar polymorfism. Metoden MakeSound åsidosättas i de härledda klasserna för att ge specifika beteenden för varje djurtyp.

Omvandla ett objekt i en basklass till en härledd klass

Gjutning i C# är processen att konvertera ett objekt av en typ till en annan typ. Gjutning används ofta när du implementerar polymorfism med hjälp av arvshierarkier, där du har en basklass och en eller flera härledda klasser.

Det finns två huvudsakliga typer av gjutning:

  • Implicit gjutning: Detta sker automatiskt när en härledd klass konverteras till en basklass. Det är säkert eftersom varje instans av en härledd klass också är en instans av basklassen.

    
    BankAccount account = new CheckingAccount();
    
    
  • Explicit gjutning: Detta kräver en cast-operator och används när du konverterar en basklass till en härledd klass. Det är inte alltid säkert eftersom inte alla instanser av en basklass är en instans av den härledda klassen.

    
    CheckingAccount checkingAccount = (CheckingAccount)account;
    
    

Omvandla objekt med hjälp av nyckelorden is och as

I C# kan du casta objekt med hjälp av nyckelorden is och as . De här nyckelorden är ett säkert sätt att kontrollera typen av objekt innan du genererar det till en annan typ. Här är några vanliga sätt att omvandla objekt i C#:

  • Använda nyckelordet is med mönstermatchning:

    
    if (account is CheckingAccount checkingAccount)
    {
        // Use checkingAccount as a CheckingAccount
    }
    
    
    • Den här syntaxen kontrollerar om account är av typen CheckingAccount.
    • Om kontrollen lyckas genererar den account till CheckingAccount och tilldelar den till variabeln checkingAccount.
    • Den här metoden är koncis och säker eftersom den kombinerar typkontrollen och gjuter i ett steg.
  • Använd nyckelordet is följt av explicit gjutning:

    
    if (account is CheckingAccount)
    {
        CheckingAccount checkingAccount = (CheckingAccount)account;
        // Use checkingAccount as a CheckingAccount
    }
    
    
    • Den här syntaxen kontrollerar om account är av typen CheckingAccount.
    • Om kontrollen lyckas genererar den uttryckligen account till CheckingAccount och tilldelar den till variabeln checkingAccount.
    • Den här metoden är mer utförlig än mönstermatchningssyntaxen, men ger mer kontroll över gjutningsprocessen.
  • Använd nyckelordet as:

    
    CheckingAccount checkingAccount = account as CheckingAccount;
    
    if (checkingAccount != null)
    {
        // Use checkingAccount as a CheckingAccount
    }
    
    
    • Den här syntaxen försöker omvandla account till CheckingAccount och tilldelar resultatet till checkingAccount.
    • Om gjutningen lyckas innehåller checkingAccount det gjutna objektet. annars är den null.
    • Den här metoden är användbar när du vill kontrollera cast-resultatet innan du använder cast-objektet. Om du till exempel vill undvika undantag och hantera felfallet korrekt.
  • När du implementerar casting bör du tänka på följande riktlinjer:

    • Använda mönstermatchning med is: Kombinerar typkontroll och gjutning i ett steg.
    • Använda nyckelordet is med explicit gjutning: Separerar typkontroll och gjuter i två steg, vilket ger mer kontroll över gjutningsprocessen.
    • Använd nyckelordet as: Försöker casta och hanterar fel på ett korrekt sätt genom att returnera null.

Att förstå dessa gjutningstekniker är viktigt för att arbeta med polymorfism och arv i C#.

Undvik vanliga fallgropar vid implementering av polymorfism

När ditt mål är arvsbaserad polymorfism, här är några saker att undvika och några saker att säkerställa:

  • Undvik att använda förseglade klasser och metoder: Förseglade klasser och metoder kan inte ärvas eller åsidosättas, vilket begränsar möjligheten att använda polymorfism. Om du förseglar en klass eller metod förhindrar du ytterligare tillägg och anpassning. Till exempel:

    
    public sealed class BankAccount { } // This class can't be inherited
    
    
  • Undvik att överanvända statiska metoder. Statiska metoder tillhör själva klassen i stället för en instans av klassen. De kan inte åsidosättas, vilket innebär att de inte deltar i polymorfism.

    
    public static void PrintMessage() { } // This method can't be overridden
    
    
  • Undvik nära koppling. Nära koppling sker när klasser eller komponenter i ett system är mycket beroende av varandra. Det innebär att ändringar i en klass direkt kan påverka andra klasser, vilket gör systemet mindre flexibelt och svårare att underhålla. Nära koppling kan leda till problem med att testa, utöka och ändra koden.

    
    public class BankAccount
    {
        public void TransferFunds(SavingsAccount savingsAccount)
        {
            // Tight coupling with SavingsAccount
        }
    }
    
    
  • Undvik att använda nyckelordet "nytt" utan någon bra anledning. Nyckelordet "nytt" döljer basklassmetoden i den härledda klassen, vilket kan leda till förvirring och oväntat beteende. Använd endast nyckelordet "nytt" när du vill dölja basklassmetoden avsiktligt.

    
    public class Dog : Animal
    {
        public new void MakeSound() // Hides the base class method. Better to use 'override'
        {
            Console.WriteLine("The dog barks.");
        }
    }
    
    
  • Kontrollera konsekventa metodsignaturer. Se till att åsidosättande metoder i härledda klasser har samma signatur som basklassmetoden. Om du ändrar metodsignaturen döljs metoden i stället för att åsidosättas.

    
    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.");
        }
    }
    
    

Sammanfattning

Med arvsbaserad polymorfism i C# kan du skapa en hierarki med klasser där härledda klasser ärver beteende och egenskaper från en basklass. Med den här arvsmekanismen kan du behandla objekt av härledda klasser som objekt i basklassen. Möjligheten att behandla härledda klassobjekt som medlemmar i en basklass gör att du kan skriva kod som fungerar med flera typer av objekt utan att känna till den specifika typen vid kompileringstiden. Genom att förstå gjutningstekniker, undvika vanliga fallgropar och följa bästa praxis kan du effektivt implementera polymorfism i dina C#-program.