Utforska arvsbaserad polymorfism
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
ismed mönstermatchning:if (account is CheckingAccount checkingAccount) { // Use checkingAccount as a CheckingAccount }- Den här syntaxen kontrollerar om
accountär av typenCheckingAccount. - Om kontrollen lyckas genererar den
accounttillCheckingAccountoch tilldelar den till variabelncheckingAccount. - Den här metoden är koncis och säker eftersom den kombinerar typkontrollen och gjuter i ett steg.
- Den här syntaxen kontrollerar om
Använd nyckelordet
isfö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 typenCheckingAccount. - Om kontrollen lyckas genererar den uttryckligen
accounttillCheckingAccountoch tilldelar den till variabelncheckingAccount. - Den här metoden är mer utförlig än mönstermatchningssyntaxen, men ger mer kontroll över gjutningsprocessen.
- Den här syntaxen kontrollerar om
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
accounttillCheckingAccountoch tilldelar resultatet tillcheckingAccount. - Om gjutningen lyckas innehåller
checkingAccountdet 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.
- Den här syntaxen försöker omvandla
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
ismed 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.
- Använda mönstermatchning med
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 inheritedUndvik 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 overriddenUndvik 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.