Esplorare il polimorfismo basato sull'ereditarietà
Il polimorfismo basato sull'ereditarietà si basa su una gerarchia di classi in cui le classi derivate ereditano il comportamento e le proprietà da una classe base. La relazione di ereditarietà consente di trattare oggetti di classi derivate come oggetti della classe base. La possibilità di trattare gli oggetti classe derivata come oggetti classe base consente di scrivere codice che funziona con più tipi di oggetti senza conoscere il tipo specifico in fase di compilazione.
L'esempio di codice seguente illustra il polimorfismo basato sull'ereditarietà 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 questo codice di esempio si noti che la classe Program crea una matrice di oggetti Animal e assegna istanze di Dog, Cate Cow agli elementi della matrice. Il metodo MakeSound viene chiamato su ogni oggetto nella matrice, dimostrando il polimorfismo. Il metodo MakeSound viene sottoposto a override nelle classi derivate per fornire un comportamento specifico per ogni tipo di animale.
Eseguire il cast di un oggetto di una classe base a una classe derivata
Il cast in C# è il processo di conversione di un oggetto di un tipo in un altro tipo. Il cast viene spesso usato quando si implementa il polimorfismo usando gerarchie di ereditarietà, in cui si ha una classe base e una o più classi derivate.
Esistono due tipi principali di serie di cast:
Cast implicito: Si verifica automaticamente quando si converte una classe derivata in una classe base. È sicuro perché ogni istanza di una classe derivata è anche un'istanza della classe base.
BankAccount account = new CheckingAccount();Cast esplicito: Richiede un operatore cast e viene usato quando si converte una classe base in una classe derivata. Non è sempre sicuro perché non tutte le istanze di una classe di base sono un'istanza della classe derivata.
CheckingAccount checkingAccount = (CheckingAccount)account;
Eseguire il cast degli oggetti usando le parole chiave is e as
In C# è possibile eseguire il cast degli oggetti usando le is parole chiave e as . Queste parole chiave forniscono un modo sicuro per controllare il tipo di un oggetto prima di eseguire il cast in un altro tipo. Ecco alcuni modi comuni per eseguire il cast degli oggetti in C#:
Uso della parola chiave
iscon criteri di ricerca:if (account is CheckingAccount checkingAccount) { // Use checkingAccount as a CheckingAccount }- Questa sintassi controlla se
accountè di tipoCheckingAccount. - Se il controllo ha esito positivo, esegue il cast di
accountaCheckingAccounte lo assegna alla variabilecheckingAccount. - Questo approccio è conciso e sicuro, poiché combina il controllo del tipo e il cast in un unico passaggio.
- Questa sintassi controlla se
Uso della parola chiave
isseguito dal cast esplicito:if (account is CheckingAccount) { CheckingAccount checkingAccount = (CheckingAccount)account; // Use checkingAccount as a CheckingAccount }- Questa sintassi controlla se
accountè di tipoCheckingAccount. - Se il controllo ha esito positivo, fa il cast esplicito di
accountinCheckingAccounte lo assegna alla variabilecheckingAccount. - Questo approccio è più dettagliato rispetto alla sintassi dei criteri di ricerca, ma offre un maggiore controllo sul processo di cast.
- Questa sintassi controlla se
Uso della parola chiave
as:CheckingAccount checkingAccount = account as CheckingAccount; if (checkingAccount != null) { // Use checkingAccount as a CheckingAccount }- Questa sintassi tenta di eseguire il cast di
accountaCheckingAccounte assegna il risultato acheckingAccount. - Se il cast ha esito positivo,
checkingAccountcontiene l'oggetto cast; in caso contrario, è Null. - Questo approccio è utile quando si desidera controllare il risultato del cast prima di usare l'oggetto sottoposto a cast. Ad esempio, quando si vogliono evitare eccezioni e gestire correttamente il caso di errore.
- Questa sintassi tenta di eseguire il cast di
Quando si implementa il cast, prendere in considerazione le linee guida seguenti:
- Uso di criteri di ricerca con
is: Combina il controllo del tipo e il cast in un unico passaggio. - Uso della parola chiave
iscon cast esplicito: Separa il controllo del tipo e il cast in due passaggi, fornendo un maggiore controllo sul processo di cast. - Uso della parola chiave
as: I tentativi di cast e gestione degli errori vengono eseguiti in modo appropriato restituendo null.
- Uso di criteri di ricerca con
Comprendere queste tecniche di cast è essenziale per lavorare con il polimorfismo e l'ereditarietà in C#.
Evitare problemi comuni quando si implementa il polimorfismo
Quando l'obiettivo è il polimorfismo basato sull'ereditarietà, ecco alcuni aspetti da evitare e alcuni aspetti da garantire:
Evitare di usare classi e metodi sealed: le classi e i metodi sealed non possono essere ereditati o sottoposti a override, che limitano la possibilità di usare il polimorfismo. Se si blocca una classe o un metodo, si impedisce un'ulteriore estensione e personalizzazione. Per esempio:
public sealed class BankAccount { } // This class can't be inheritedEvitare di sovrautilizzare i metodi statici. I metodi statici appartengono alla classe stessa anziché a un'istanza della classe . Non possono essere sottoposti a override, il che significa che non partecipano al polimorfismo.
public static void PrintMessage() { } // This method can't be overriddenEvitare un accoppiamento stretto. L'accoppiamento stretto si verifica quando le classi o i componenti in un sistema dipendono l'uno dall'altro. Ciò significa che le modifiche in una classe possono influire direttamente su altre classi, rendendo il sistema meno flessibile e più difficile da gestire. L'accoppiamento stretto può causare difficoltà nel test, nell'estensione e nella modifica del codice.
public class BankAccount { public void TransferFunds(SavingsAccount savingsAccount) { // Tight coupling with SavingsAccount } }Evitare di usare la parola chiave "new" senza un buon motivo. La parola chiave 'new' nasconde il metodo della classe base nella classe derivata, che può causare confusione e comportamento imprevisto. Usare la parola chiave "new" solo quando si intende nascondere intenzionalmente il metodo della classe base.
public class Dog : Animal { public new void MakeSound() // Hides the base class method. Better to use 'override' { Console.WriteLine("The dog barks."); } }Assicurarsi firme di metodi coerenti. Assicurarsi che i metodi sottoposti a override nelle classi derivate abbiano la stessa firma del metodo della classe base. La modifica della firma del metodo comporterà la disattivazione del metodo anziché l'override.
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."); } }
Sommario
Il polimorfismo basato sull'ereditarietà in C# consente di creare una gerarchia di classi in cui le classi derivate ereditano il comportamento e le proprietà da una classe base. Questo meccanismo di ereditarietà consente di trattare oggetti di classi derivate come oggetti della classe di base. La possibilità di trattare gli oggetti classe derivata come membri di una classe di base consente di scrivere codice che funziona con più tipi di oggetti senza conoscere il tipo specifico in fase di compilazione. Comprendendo le tecniche di cast, evitando problemi comuni e seguendo le procedure consigliate, è possibile implementare efficacemente il polimorfismo nelle applicazioni C#.