Udforsk arvebaseret polymorfi

Fuldført

Nedarvningsbaseret polymorfi er baseret på et klassehierarki, hvor afledte klasser nedarver funktionsmåde og egenskaber fra en basisklasse. Nedarvningsrelationen giver dig mulighed for at behandle objekter af afledte klasser som objekter i basisklassen. Når du kan behandle afledte klasseobjekter som basisklasseobjekter, kan du skrive kode, der fungerer sammen med flere typer objekter, uden at kende den specifikke type på kompileringstidspunktet.

Følgende kodeeksempel viser nedarvningsbaseret polymorfi 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();
        }
    }
}

Bemærk i denne eksempelkode, at klassen Program opretter en matrix af Animal objekter og tildeler forekomster af Dog, Catog Cow til matrixelementerne. Metoden MakeSound kaldes for hvert objekt i matrixen og demonstrerer polymorfi. Den MakeSound metode tilsidesættes i de afledte klasser for at give specifik funktionsmåde for hver dyretype.

Cast et objekt af en basisklasse til en afledt klasse

Casting i C# er processen med at konvertere et objekt af én type til en anden type. Casting bruges ofte, når du implementerer polymorfi ved hjælp af nedarvningshierarkier, hvor du har en basisklasse og en eller flere afledte klasser.

Der er to hovedtyper af casting:

  • Implicit casting: Dette sker automatisk, når en afledt klasse konverteres til en basisklasse. Det er sikkert, fordi alle forekomster af en afledt klasse også er en forekomst af basisklassen.

    
    BankAccount account = new CheckingAccount();
    
    
  • Eksplicit casting: Dette kræver en castoperator og bruges ved konvertering af en basisklasse til en afledt klasse. Det er ikke altid sikkert, fordi ikke alle forekomster af en basisklasse er en forekomst af den afledte klasse.

    
    CheckingAccount checkingAccount = (CheckingAccount)account;
    
    

Cast objekter ved hjælp af nøgleordene is og as

I C#kan du caste objekter ved hjælp af nøgleordene is og as . Disse nøgleord giver en sikker måde at kontrollere typen af et objekt på, før du kaster det til en anden type. Her er nogle almindelige måder at caste objekter på i C#:

  • Brug af nøgleordet is med mønstermatch:

    
    if (account is CheckingAccount checkingAccount)
    {
        // Use checkingAccount as a CheckingAccount
    }
    
    
    • Denne syntaks kontrollerer, om account er af typen CheckingAccount.
    • Hvis kontrollen lykkes, sendes account til CheckingAccount og tildeler den til variablen checkingAccount.
    • Denne fremgangsmåde er præcis og sikker, da den kombinerer typekontrollen og caster i ét trin.
  • Brug af nøgleordet is efterfulgt af eksplicit casting:

    
    if (account is CheckingAccount)
    {
        CheckingAccount checkingAccount = (CheckingAccount)account;
        // Use checkingAccount as a CheckingAccount
    }
    
    
    • Denne syntaks kontrollerer, om account er af typen CheckingAccount.
    • Hvis kontrollen lykkes, konverteres account eksplicit til CheckingAccount og tildeler den til variablen checkingAccount.
    • Denne fremgangsmåde er mere detaljeret end syntaksen for matchning af mønstre, men giver mere kontrol over castingprocessen.
  • Brug af nøgleordet as:

    
    CheckingAccount checkingAccount = account as CheckingAccount;
    
    if (checkingAccount != null)
    {
        // Use checkingAccount as a CheckingAccount
    }
    
    
    • Denne syntaks forsøger at konvertere account til CheckingAccount og tildeler resultatet til checkingAccount.
    • Hvis castet lykkes, indeholder checkingAccount castobjektet. Ellers er den null.
    • Denne fremgangsmåde er nyttig, når du vil kontrollere castresultatet, før du bruger castobjektet. Hvis du f.eks. vil undgå undtagelser og håndtere fejlcasen korrekt.
  • Når du implementerer casting, skal du overveje følgende retningslinjer:

    • Brug af mønster, der matcher med is: Kombinerer typekontrol og cast i ét trin.
    • Brug af is nøgleord med eksplicit cast: Adskiller typekontrol og caster i to trin, hvilket giver mere kontrol over castingprocessen.
    • Brug af nøgleordet as: Forsøger at caste og håndtere fejl korrekt ved at returnere null.

Forståelse af disse casting teknikker er afgørende for at arbejde med polymorfi og arv i C#.

Undgå almindelige faldgruber ved implementering af polymorfi

Når dit mål er arvebaseret polymorfi, er her nogle ting, du skal undgå, og nogle ting, du skal sikre:

  • Undgå at bruge forseglede klasser og metoder: Forseglede klasser og metoder kan ikke nedarves eller tilsidesættes, hvilket begrænser muligheden for at bruge polymorfi. Hvis du forsegler en klasse eller metode, forhindrer du yderligere udvidelse og tilpasning. For eksempel:

    
    public sealed class BankAccount { } // This class can't be inherited
    
    
  • Undgå overusing af statiske metoder. Statiske metoder tilhører selve klassen i stedet for en forekomst af klassen. De kan ikke tilsidesættes, hvilket betyder, at de ikke deltager i polymorfi.

    
    public static void PrintMessage() { } // This method can't be overridden
    
    
  • Undgå tæt kobling. Tæt kobling opstår, når klasser eller komponenter i et system er meget afhængige af hinanden. Det betyder, at ændringer i én klasse direkte kan påvirke andre klasser, hvilket gør systemet mindre fleksibelt og sværere at vedligeholde. Tæt kobling kan medføre problemer med test, udvidelse og ændring af koden.

    
    public class BankAccount
    {
        public void TransferFunds(SavingsAccount savingsAccount)
        {
            // Tight coupling with SavingsAccount
        }
    }
    
    
  • Undgå at bruge nøgleordet 'ny' uden en god grund. Nøgleordet 'new' skjuler basisklassemetoden i den afledte klasse, hvilket kan føre til forvirring og uventet funktionsmåde. Brug kun nøgleordet 'new', når du bevidst vil skjule basisklassemetoden.

    
    public class Dog : Animal
    {
        public new void MakeSound() // Hides the base class method. Better to use 'override'
        {
            Console.WriteLine("The dog barks.");
        }
    }
    
    
  • Sørg for ensartede metodesignaturer. Sørg for, at tilsidesatte metoder i afledte klasser har samme signatur som basisklassemetoden. Hvis du ændrer metodesignaturen, skjules metoden i stedet for at tilsidesætte den.

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

Resumé

Arvebaseret polymorfi i C# giver dig mulighed for at oprette et hierarki af klasser, hvor afledte klasser nedarver funktionsmåde og egenskaber fra en basisklasse. Denne nedarvningsmekanisme giver dig mulighed for at behandle objekter af afledte klasser som objekter i basisklassen. Muligheden for at behandle afledte klasseobjekter som medlemmer af en basisklasse giver dig mulighed for at skrive kode, der fungerer sammen med flere typer objekter, uden at kende den specifikke type på kompileringstidspunktet. Ved at forstå castingteknikker, undgå almindelige faldgruber og følge bedste praksis kan du effektivt implementere polymorfi i dine C#-programmer.