Accedere ai membri della classe di base da una classe derivata
Una classe derivata che sostituisce o esegue l'override di un metodo o una proprietà della classe di base può comunque accedere al metodo o alla proprietà della classe di base usando la parola chiave base. In questo modo è possibile chiamare costruttori, metodi e proprietà della classe di base dai membri sottoposti a override di una classe derivata. Usando la parola chiave base, è possibile avere la certezza che la classe derivata riutilizzi ed estenda correttamente le funzionalità offerte dalla classe di base.
La parola chiave base consente di eseguire le attività seguenti:
- Chiamare un metodo della classe di base da un metodo sottoposto a override della classe derivata.
- Implementare un costruttore della classe di base dal costruttore della classe derivata.
La parola chiave base presenta le restrizioni seguenti:
- La parola chiave
basepuò essere usata solo in un costruttore, in un metodo di istanza o in una funzione di accesso alle proprietà dell'istanza. - La parola chiave
basenon può essere usata in un metodo statico. Se si tenta di usare la parola chiavebasein un metodo statico, verrà generato un errore.
Quando si implementa la parola chiave base in una classe derivata, il codice usa la classe di base specificata nella dichiarazione della classe. Se, ad esempio, nella dichiarazione di classe si specifica la classe ClassC : ClassB, la parola chiave base consentirà al codice di accedere ai membri di ClassB da ClassC. Non importa se la classe ClassB eredita dalla classe ClassA.
Accedere alle proprietà e ai metodi della classe di base da una classe derivata
L'accesso alle proprietà e ai metodi di una classe di base da una classe derivata è un requisito comune durante l'implementazione dell'ereditarietà. Il codice seguente illustra la sintassi per implementare la parola chiave base:
base.MemberName
Si noti che la parola chiave base e il nome del membro della classe di base sono separati da un punto (.). L’elemento MemberName può essere una proprietà, un metodo o un campo della classe di base.
Il codice seguente illustra come accedere alle proprietà e ai metodi della classe di base da una classe derivata:
// create an instance of the derived classes
DerivedClass1 derivedClass1 = new DerivedClass1();
// demonstrate the overridden methods of the derived class
Console.WriteLine("Calling the methods of DerivedClass1...\n");
Console.WriteLine($"Method1 in the derived class overrides the base class and provides a custom message: {derivedClass1.Method1()}");
derivedClass1.Method2();
/*Output:
Calling the methods of DerivedClass1...
Method1 in the base class is abstract and can't be called.
Method1 in the derived class overrides the base class and provides a custom message: Message from the overridden Method1 in DerivedClass1
Method2 in the derived class calls base.Method2 (reuses the base class implementation)
Method2 in the base class implements common behavior and returns true/false
Method2 in the derived class accesses base class Property2: Base - Property2
Method2 in the derived class uses base class members to modify and extend functionality
*/
public abstract class BaseClass
{
public abstract string Property1 { get; set; }
public virtual string Property2 { get; set; } = "Base - Property2";
public abstract string Method1();
public virtual bool Method2()
{
Console.WriteLine("Method2 in the base class implements common behavior and returns true/false");
return true;
}
}
public class DerivedClass1 : BaseClass
{
public override string Property1 { get; set; } = "Derived - Property1";
public new string Property2 { get; set; } = "Derived - Property2";
public override string Method1()
{
// Method1 of the base class is abstract and can't be called
Console.WriteLine($"Method1 in the base class is abstract and can't be called.");
// Return the base.Method1 response additional information specific to DerivedClass1
return $"Message from the overridden Method1 in DerivedClass1";
}
public override bool Method2()
{
// Call base class method to implement common behavior
Console.WriteLine($"\nMethod2 in the derived class calls base.Method2 (reuses the base class implementation)");
bool baseMethod2Success = base.Method2();
// Access base class Property2
string baseProperty2Value = base.Property2;
Console.WriteLine($"Method2 in the derived class accesses base class Property2: {baseProperty2Value}");
// implement derived class logic that involves base class information
if (baseMethod2Success && baseProperty2Value == "Base - Property2")
{
Console.WriteLine("\nMethod2 in the derived class uses base class members to modify and extend functionality");
return true;
}
else
{
Console.WriteLine("Method2 in the derived class can implement alternate behavior");
}
return false;
}
}
In questo codice di esempio, la classe DerivedClass1 eredita da BaseClass ed esegue l'override dei metodi di cui dispone per estenderne le funzionalità. Il codice implementa i passaggi seguenti:
Viene creata un'istanza di
DerivedClass1usando l'istruzioneDerivedClass1 derivedClass1 = new DerivedClass1();. Questa istanza di classe derivata consente di chiamare e illustrare i metodi sottoposti a override della classe derivata.Il codice chiama l’elemento
Method1della classe derivata da un'istruzioneConsole.WriteLine. L’elementoMethod1sottoposto a override non può accedere all’elementoMethod1astratto della classe di base. Fornisce invece una propria implementazione che restituisce una stringa che indica che è univoca per la classe derivata.Il codice chiama l’elemento
Method2della classe derivata. L’elementoMethod2sottoposto a override usabase.Method2per riutilizzare l'implementazione dell’elementoMethod2della classe di base. Il metodo accede all’elementoProperty2della classe di base e ne stampa il valore. Il metodo sottoposto a override usa quindi il valore booleano restituito dall’elementoMethod2della classe di base e il valore dell’elementoProperty2per estendere la funzionalità diMethod2o implementare un comportamento alternativo. Questo passaggio illustra come la classe derivata può sfruttare e modificare il comportamento del metodo della classe di base.
Nota
È consigliabile che ogni membro virtuale usi base per chiamare l'implementazione della classe di base del membro nella relativa implementazione. Consentire il comportamento della classe di base permette alla classe derivata di concentrarsi sull'implementazione del comportamento specifico della classe derivata. Se l'implementazione della classe di base non viene chiamata, spetta alla classe derivata rendere il proprio comportamento compatibile con quello della classe di base.
Accedere ai costruttori della classe di base da una classe derivata
È possibile accedere ai costruttori di classe disponibili nella classe di base dai costruttori della classe derivata usando la parola chiave base.
Il codice seguente illustra come accedere ai costruttori della classe di base da una classe derivata:
// create an instance of the derived classes
DerivedClass1 derivedClass1 = new DerivedClass1("Derived1 - Property1", "Derived1 - Property2");
// demonstrate the overridden methods of the derived class
Console.WriteLine("Calling the methods of DerivedClass1...\n");
Console.WriteLine($"Method1 in the derived class appends derived class information to the return value: {derivedClass1.Method1()}");
derivedClass1.Method2();
/*Output:
Calling the methods of DerivedClass1...
Method1 in the derived class calls base.Method1. base.Method1 returns: base.Method1 results
Method1 in the derived class appends derived class information to the return value: base.Method1 results - plus information specific to DerivedClass1
Method2 in the derived class calls base.Method2 (reuses the base class implementation)
Method2 in the base class implements common behavior and returns true/false
Method2 in the derived class accesses base class Property2: Base - Property2
Method2 in the derived class uses base class members to modify and extend functionality
*/
public abstract class BaseClass
{
public abstract string Property1 { get; set; }
public virtual string Property2 { get; set; }
public BaseClass(string property1, string property2)
{
Property1 = property1;
Property2 = property2;
}
public virtual string Method1()
{
return "base.Method1 results";
}
public virtual bool Method2()
{
Console.WriteLine("Method2 in the base class implements common behavior and returns true/false");
return true;
}
}
public class DerivedClass1 : BaseClass
{
public override string Property1 { get; set; }
public new string Property2 { get; set; }
public DerivedClass1(string property1, string property2) : base(property1, "Base - Property2")
{
Property1 = property1;
Property2 = property2;
}
public override string Method1()
{
// Method1 of the base class is now virtual
Console.WriteLine($"Method1 in the derived class calls base.Method1. base.Method1 returns: {base.Method1()}");
// Return the base.Method1 response additional information specific to DerivedClass1
return $"{base.Method1()} - plus information specific to DerivedClass1";
}
public override bool Method2()
{
// Call base class method to implement common behavior
Console.WriteLine($"\nMethod2 in the derived class calls base.Method2 (reuses the base class implementation)");
bool baseMethod1Success = base.Method2();
// Access base class Property2
string baseProperty2Value = base.Property2;
Console.WriteLine($"Method2 in the derived class accesses base class Property2: {baseProperty2Value}");
// implement derived class logic that involves base class information
if (baseMethod1Success && baseProperty2Value == "Base - Property2")
{
Console.WriteLine("\nMethod2 in the derived class uses base class members to modify and extend functionality");
return true;
}
else
{
Console.WriteLine("Method2 in the derived class can implement alternate behavior");
}
return false;
}
}
È importante chiamare il costruttore della classe di base dal costruttore della classe derivata quando, ad esempio, il costruttore della classe di base inizializza le proprietà comuni usate dalla classe derivata. Chiamando il costruttore della classe di base dal costruttore della classe derivata, si ha la certezza che le proprietà comuni vengano inizializzate prima che venga eseguito il costruttore della classe derivata.
Osservare il codice seguente:
public abstract class Vehicle
{
public virtual int Speed { get; set; }
public virtual int Fuel { get; set; }
public Vehicle(int speed, int fuel)
{
Speed = speed;
Fuel = fuel;
}
public virtual void Drive()
{
Console.WriteLine("Vehicle is driving");
}
}
public class Car : Vehicle
{
public int NumberOfDoors { get; set; }
public int TrunkCapacity { get; set; }
public Car(int speed, int fuel, int numberOfDoors) : base(speed, fuel)
{
NumberOfDoors = numberOfDoors;
// Initialize TrunkCapacity based on the Speed and Fuel properties of the base class
TrunkCapacity = CalculateTrunkCapacity(Speed, Fuel);
}
private int CalculateTrunkCapacity(int speed, int fuel)
{
// Example logic to calculate trunk capacity based on speed and fuel
return (speed + fuel) / 2;
}
public override void Drive()
{
base.Drive();
Console.WriteLine("Car is driving with additional features");
}
}
class Program
{
static void Main()
{
Car car = new Car(100, 50, 4);
Console.WriteLine($"Speed: {car.Speed}, Fuel: {car.Fuel}, NumberOfDoors: {car.NumberOfDoors}, TrunkCapacity: {car.TrunkCapacity}");
car.Drive();
}
}
Si noti che il costruttore della classe Car chiama il costruttore della classe di base usando la parola chiave base. Chiamando il costruttore della classe di base si garantisce in primo luogo che le proprietà Speed e Fuel della classe di base Vehicle vengano inizializzate correttamente prima che venga eseguito il costruttore della classe Car. Questa sequenza di eventi è importante poiché la proprietà TrunkCapacity della classe Car viene inizializzata usando le proprietà Speed e Fuel della classe di base Vehicle.
Riepilogo
Quando si accede ai membri della classe di base da una classe derivata, attenersi alle indicazioni seguenti:
- Usare la parola chiave
baseper accedere ai membri della classe di base da una classe derivata. - Usare la parola chiave
baseper chiamare i costruttori della classe di base dai costruttori della classe derivata. - Usare la parola chiave
baseper accedere ai campi, alle proprietà e ai metodi della classe di base dai metodi sottoposti a override di una classe derivata.