Få tilgang til grunnklassemedlemmer fra en avledet klasse
En avledet klasse som erstatter eller overstyrer en basisklassemetode eller -egenskap, har fortsatt tilgang til metoden eller egenskapen på basisklassen ved hjelp av nøkkelordet base. Dette gjør det mulig å kalle grunnleggende klassekonstruktører, metoder og egenskaper fra overstyrte medlemmer av en avledet klasse. Ved å bruke nøkkelordet base, kan du sikre at den avledede klassen gjenbruker på riktig måte og utvider funksjonaliteten som leveres av basisklassen.
Nøkkelordet base brukes til å utføre følgende oppgaver:
- Hvis du vil kalle en basisklassemetode fra en overstyrt metode for den avledede klassen.
- Implementere en konstruktør i grunnklassen fra konstruktøren av den avledede klassen.
Nøkkelordet base har følgende begrensninger:
- Nøkkelordet
basekan bare brukes i en konstruktør, en forekomstmetode eller en forekomstegenskapstilgangsør. - Nøkkelordet
basekan ikke brukes i en statisk metode. Hvis du prøver å brukebasenøkkelord i en statisk metode, genereres det en feil.
Når du implementerer base nøkkelord i en avledet klasse, bruker koden grunnklassen som er angitt i klassedeklarasjonen. Hvis du for eksempel angir klasse ClassC : ClassB i klassedeklarasjonen, gir base nøkkelord koden tilgang til medlemmene av ClassB fra ClassC. Det spiller ingen rolle om klassen ClassB arver fra klasse ClassA.
Egenskaper og metoder for access-basisklasse fra en avledet klasse
Tilgang til egenskapene og metodene til en basisklasse fra en avledet klasse er et vanlig krav når du implementerer arv. Følgende kode demonstrerer syntaksen for implementering av nøkkelordet base:
base.MemberName
Legg merke til at base nøkkelord og navnet på grunnklassemedlemmet er atskilt med et punktum (.). Den MemberName kan være en egenskap, metode eller et felt i basisklassen.
Følgende kode viser hvordan du får tilgang til grunnleggende klasseegenskaper og metoder fra en avledet klasse:
// 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;
}
}
I dette kodeeksempelet arver DerivedClass1-klassen fra BaseClass og overstyrer metodene for å utvide funksjonaliteten. Koden implementerer følgende trinn:
En forekomst av
DerivedClass1opprettes ved hjelp av setningenDerivedClass1 derivedClass1 = new DerivedClass1();. Denne avledede klasseforekomsten brukes til å ringe og demonstrere de overstyrte metodene i den avledede klassen.Koden kaller opp
Method1av den avledede klassen fra enConsole.WriteLinesetning. Den overstyrteMethod1får ikke tilgang til sammendragetMethod1av basisklassen. I stedet gir den sin egen implementering som returnerer en streng som indikerer at den er unik for den avledede klassen.Koden kaller
Method2av den avledede klassen. Den overstyrteMethod2brukerbase.Method2til å bruke grunnklassensMethod2implementering på nytt. Metoden får tilgang til grunnklassensProperty2og skriver ut verdien. Den overstyrte metoden bruker deretter den boolske verdien som returneres av grunnklassensMethod2og verdien avProperty2, til enten å utvideMethod2-funksjonaliteten eller implementere alternativ virkemåte. Dette trinnet viser hvordan den avledede klassen kan bygge på og endre virkemåten til basisklassemetoden.
Notat
Det er anbefalt fremgangsmåte for virtuelle medlemmer å bruke base til å kalle den grunnleggende klasseimplementeringen av medlemmet i sin egen implementering. Hvis du lar den grunnleggende klassevirkemåten forekomme, kan den avledede klassen konsentrere seg om å implementere virkemåte som er spesifikk for den avledede klassen. Hvis den grunnleggende klasseimplementeringen ikke kalles, er det opp til den avledede klassen å gjøre virkemåten kompatibel med virkemåten til basisklassen.
Access-basisklassekonstruktører fra en avledet klasse
Klassekonstruktører i basisklassen kan nås fra konstruktører av den avledede klassen ved hjelp av nøkkelordet base.
Følgende kode viser hvordan du får tilgang til grunnleggende klassekonstruktører fra en avledet klasse:
// 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;
}
}
Det er viktig å kalle basisklassekonstruktøren fra den avledede klassekonstruktøren. Når for eksempel basisklassekonstruktøren initialiserer vanlige egenskaper som brukes av den avledede klassen. Ved å kalle basisklassekonstruktøren fra den avledede klassekonstruktøren, sikrer du at de vanlige egenskapene initialiseres før den avledede klassekonstruktøren utføres.
Vurder følgende kode:
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();
}
}
Legg merke til at Car klassekonstruktøren kaller basisklassekonstruktøren ved hjelp av nøkkelordet base. Når du kaller basisklassekonstruktøren, sikrer du først at Speed og Fuel egenskapene til Vehicle basisklasse initialiseres riktig før Car klassekonstruktøren utføres. Denne sekvensen av hendelser er viktig fordi TrunkCapacity egenskapen til Car klassen initialiseres ved hjelp av Speed og Fuel egenskapene for Vehicle basisklassen.
Sammendrag
Vurder følgende retningslinjer når du får tilgang til grunnleggende klassemedlemmer fra en avledet klasse:
- Bruk nøkkelordet
basetil å få tilgang til grunnleggende klassemedlemmer fra en avledet klasse. - Bruk
basenøkkelord til å kalle grunnleggende klassekonstruktører fra avledede klassekonstruktører. - Bruk nøkkelordet
basetil å få tilgang til basisklassefelt, egenskaper og metoder fra overstyrte metoder i en avledet klasse.