Op overname gebaseerde polymorfisme verkennen
Polymorfisme op basis van overname is gebaseerd op een klassehiërarchie waarbij afgeleide klassen gedrag en eigenschappen overnemen van een basisklasse. Met de overnamerelatie kunt u objecten van afgeleide klassen behandelen als objecten van de basisklasse. Als u afgeleide klasseobjecten als basisklasseobjecten kunt behandelen, kunt u code schrijven die met meerdere typen objecten werkt zonder dat u het specifieke type tijdens het compileren kent.
In het volgende codevoorbeeld ziet u polymorfisme op basis van overname in 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();
}
}
}
In deze voorbeeldcode ziet u dat de Program-klasse een matrix van Animal objecten maakt en exemplaren van Dog, Caten Cow toewijst aan de matrixelementen. De methode MakeSound wordt aangeroepen op elk object in de matrix, waarmee polymorfisme wordt gedemonstreerd. De MakeSound methode wordt overschreven in de afgeleide klassen om specifiek gedrag voor elk diertype te bieden.
Een object van een basisklasse casten naar een afgeleide klasse
Casten in C# is het proces van het converteren van een object van het ene type naar een ander type. Casten wordt vaak gebruikt bij het implementeren van polymorfisme met behulp van overnamehiërarchieën, waarbij u een basisklasse en een of meer afgeleide klassen hebt.
Er zijn twee hoofdtypen casting:
Impliciete cast-conversie: dit gebeurt automatisch bij het converteren van een afgeleide klasse naar een basisklasse. Het is veilig omdat elk exemplaar van een afgeleide klasse ook een exemplaar van de basisklasse is.
BankAccount account = new CheckingAccount();Expliciete cast-conversie: hiervoor is een cast-operator vereist en wordt gebruikt bij het converteren van een basisklasse naar een afgeleide klasse. Het is niet altijd veilig omdat niet elk exemplaar van een basisklasse een exemplaar van de afgeleide klasse is.
CheckingAccount checkingAccount = (CheckingAccount)account;
Objecten casten met behulp van de trefwoorden is en as
In C# kunt u objecten casten met behulp van de is en as trefwoorden. Deze trefwoorden bieden een veilige manier om het type van een object te controleren voordat het naar een ander type wordt gecast. Hier volgen enkele veelvoorkomende manieren om objecten in C# te casten:
Het
istrefwoord gebruiken met patroonkoppeling:if (account is CheckingAccount checkingAccount) { // Use checkingAccount as a CheckingAccount }- Met deze syntaxis wordt gecontroleerd of
accountvan het typeCheckingAccountis. - Als de controle is geslaagd, wordt
accountomgezet inCheckingAccounten wordt deze toegewezen aan de variabelecheckingAccount. - Deze benadering is beknopt en veilig, omdat deze de typecontrole combineert en in één stap cast.
- Met deze syntaxis wordt gecontroleerd of
Gebruik het
istrefwoord gevolgd door expliciete cast-conversie:if (account is CheckingAccount) { CheckingAccount checkingAccount = (CheckingAccount)account; // Use checkingAccount as a CheckingAccount }- Met deze syntaxis wordt gecontroleerd of
accountvan het typeCheckingAccountis. - Als de controle is geslaagd, wordt
accountexpliciet omgezet inCheckingAccounten toegewezen aan de variabelecheckingAccount. - Deze benadering is uitgebreider dan de patroonkoppelingssyntaxis, maar biedt meer controle over het cast-proces.
- Met deze syntaxis wordt gecontroleerd of
Het trefwoord
asgebruiken:CheckingAccount checkingAccount = account as CheckingAccount; if (checkingAccount != null) { // Use checkingAccount as a CheckingAccount }- Deze syntaxis probeert
accountte casten naarCheckingAccounten wijst het resultaat toe aancheckingAccount. - Als de cast is geslaagd,
checkingAccounthet cast-object bevat; anders is het null. - Deze methode is handig als u het cast-resultaat wilt controleren voordat u het cast-object gebruikt. Als u bijvoorbeeld uitzonderingen wilt voorkomen en de foutcase probleemloos wilt afhandelen.
- Deze syntaxis probeert
Houd bij het implementeren van cast-conversie rekening met de volgende richtlijnen:
- Patroonkoppeling gebruiken met
is: Combineert typecontrole en cast in één stap. - Met behulp van het
istrefwoord met expliciete cast: Scheidt typecontrole en cast in twee stappen, wat meer controle biedt over het cast-proces. - Met behulp van het
astrefwoord: pogingen casten en afhandelen foutloos door null te retourneren.
- Patroonkoppeling gebruiken met
Het begrijpen van deze cast-technieken is essentieel voor het werken met polymorfisme en overname in C#.
Vermijd veelvoorkomende valkuilen bij het implementeren van polymorfisme
Wanneer uw doel is gebaseerd op polymorfisme op basis van overname, zijn er enkele dingen die u moet vermijden en enkele dingen om ervoor te zorgen:
Vermijd het gebruik van verzegelde klassen en methoden: Verzegelde klassen en methoden kunnen niet worden overgenomen of overschreven, waardoor de mogelijkheid om polymorfisme te gebruiken wordt beperkt. Als u een klasse of methode verzegelt, voorkomt u verdere uitbreiding en aanpassing. Bijvoorbeeld:
public sealed class BankAccount { } // This class can't be inheritedVermijd overusing van statische methoden. Statische methoden behoren tot de klasse zelf in plaats van een exemplaar van de klasse. Ze kunnen niet worden overschreven, wat betekent dat ze niet deelnemen aan polymorfisme.
public static void PrintMessage() { } // This method can't be overriddenVermijd strakke koppeling. Strakke koppeling treedt op wanneer klassen of onderdelen in een systeem sterk afhankelijk zijn van elkaar. Dit betekent dat wijzigingen in de ene klasse rechtstreeks van invloed kunnen zijn op andere klassen, waardoor het systeem minder flexibel en moeilijker te onderhouden is. Een strakke koppeling kan leiden tot problemen bij het testen, uitbreiden en wijzigen van de code.
public class BankAccount { public void TransferFunds(SavingsAccount savingsAccount) { // Tight coupling with SavingsAccount } }Vermijd het gebruik van het trefwoord 'nieuw' zonder een goede reden. Het trefwoord 'nieuw' verbergt de basisklassemethode in de afgeleide klasse, wat kan leiden tot verwarring en onverwacht gedrag. Gebruik alleen het trefwoord 'nieuw' wanneer u de basisklassemethode opzettelijk wilt verbergen.
public class Dog : Animal { public new void MakeSound() // Hides the base class method. Better to use 'override' { Console.WriteLine("The dog barks."); } }Zorg voor consistente methodehandtekeningen. Zorg ervoor dat overschreven methoden in afgeleide klassen dezelfde handtekening hebben als de basisklassemethode. Als u de handtekening van de methode wijzigt, wordt de methode verborgen in plaats van te overschrijven.
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."); } }
Samenvatting
Met polymorfisme op basis van overname in C# kunt u een hiërarchie van klassen maken waarbij afgeleide klassen gedrag en eigenschappen overnemen van een basisklasse. Met dit overnamemechanisme kunt u objecten van afgeleide klassen behandelen als objecten van de basisklasse. Met de mogelijkheid om afgeleide klasseobjecten als leden van een basisklasse te behandelen, kunt u code schrijven die met meerdere typen objecten werkt zonder dat u het specifieke type tijdens het compileren kent. Door het begrijpen van cast-technieken, het vermijden van veelvoorkomende valkuilen en het volgen van best practices, kunt u effectief polymorfisme implementeren in uw C#-toepassingen.