Konfigurera bas- och härledda klasser
Termerna basklassen och härledd klass används för att beskriva relationen mellan klasser i en arvshierarki. En basklass används för att definiera en gemensam uppsättning attribut och beteenden som andra klasser ärver. En härledd klass används för att definiera en specialiserad uppsättning attribut och beteenden som utökar eller ändrar basklassen.
Granska arvets transitiva karaktär
I C# kan en klass bara ärva från en basklass. Den här begränsningen kallas för enskilt arv. Med ett enda arv kan en härledd klass komma åt egenskaperna och metoderna för en enskild basklass, vilket främjar en tydlig och enkel hierarki. Begreppet flera arv stöds inte i C#. Den här begränsningen undviker de komplexiteter och tvetydigheter som kan uppstå vid ärvning från flera basklasser. I stället använder C# gränssnitt för att uppnå liknande funktioner.
Även om en klass bara kan ärva från en basklass är arv transitivt. Det innebär att om en klass C ärver från klass B och klass B ärver från klass A ärver klass C de medlemmar som deklarerats i både klass B och klass A. Den här egenskapen möjliggör djupare hierarkier och ytterligare återanvändning av kod.
Tänk dig till exempel ett system för fordonshantering där du har en basklass Vehicle, en härledd klass Car som ärver från Vehicleoch en annan härledd klass ElectricCar som ärver från Car. I den här hierarkin ärver ElectricCar medlemmar från både Car och Vehicle, vilket visar arvets transitiva karaktär.
public class Vehicle
{
public string Make { get; set; }
public string Model { get; set; }
public void StartEngine()
{
Console.WriteLine("Engine started.");
}
public void StopEngine()
{
Console.WriteLine("Engine stopped.");
}
}
public class Car : Vehicle
{
public int NumberOfDoors { get; set; }
public void OpenTrunk()
{
Console.WriteLine("Trunk opened.");
}
public void HonkHorn()
{
Console.WriteLine("Horn honked.");
}
public void LockDoors()
{
Console.WriteLine("Doors locked.");
}
}
public class ElectricCar : Car
{
public int BatteryCapacity { get; set; }
public void ChargeBattery()
{
Console.WriteLine("Battery charging.");
}
public void DisplayBatteryStatus()
{
Console.WriteLine("Battery status displayed.");
}
}
public class CombustionEngineCar : Car
{
public int FuelCapacity { get; set; }
public void Refuel()
{
Console.WriteLine("Car refueled.");
}
public void CheckOilLevel()
{
Console.WriteLine("Oil level checked.");
}
}
Det här exemplet visar ett enkelt fordonshanteringssystem med följande klasser:
Vehicle-klass: BasklassenVehicleinnehåller vanliga egenskaper och metoder för alla fordon, till exempel Make, Model, StartEngine och StopEngine.Car-klass: KlassenCarärver frånVehicleoch lägger till specifika egenskaper och metoder för bilar, till exempelNumberOfDoors,OpenTrunk,HonkHornochLockDoors.ElectricCar-klass: KlassenElectricCarärver frånCaroch lägger till egenskaper och metoder som är specifika för elbilar, till exempelBatteryCapacity,ChargeBatteryochDisplayBatteryStatus.CombustionEngineCar-klass: KlassenCombustionEngineCarärver också frånCaroch lägger till egenskaper och metoder som är specifika för förbränningsmotorbilar, till exempelFuelCapacity,RefuelochCheckOilLevel.
I det här exemplet ärver klassen Car medlemmar från klassen Vehicle och ElectricCar och CombustionEngineCar ärver medlemmar från klassen Car. Den här hierarkin visar arvets transitiva karaktär, där ElectricCar och CombustionEngineCar ärver medlemmar från både Car och Vehicle.
Granska arv och synlighet för medlemmar
När en klass ärver från en basklass gäller följande regler:
- Statiska konstruktorer och instanskonstruktorer ärvs inte.
- Alla andra medlemmar i basklassen ärvs, men åtkomstmodifierare påverkar deras synlighet i den härledda klassen. Åtkomstmodifierare är:
public,protected,internalochprivate.
Offentliga medlemmar
Offentliga medlemmar är tillgängliga från alla kod som har åtkomst till klassen. Härledda klasser ärver offentliga medlemmar och de är tillgängliga utanför klasshierarkin.
public class BaseClass
{
public int publicField;
public void PublicMethod() { }
}
public class DerivedClass : BaseClass
{
public void AccessPublicMember()
{
publicField = 10;
PublicMethod();
}
}
I det här exemplet ärver DerivedClasspublicField och PublicMethod medlemmar från BaseClass. Metoden AccessPublicMember i DerivedClass kan komma åt dessa medlemmar. Offentliga medlemmar är också tillgängliga från kod som ligger utanför klasshierarkin.
Skyddade medlemmar
Skyddade medlemmar är tillgängliga i klassen där de deklareras och inom härledda klasser. De är inte tillgängliga utanför klasshierarkin.
public class BaseClass
{
protected int protectedField;
protected void ProtectedMethod() { }
}
public class DerivedClass : BaseClass
{
public void AccessProtectedMember()
{
protectedField = 10;
ProtectedMethod();
}
}
I det här exemplet ärver DerivedClassprotectedField och ProtectedMethod medlemmar från BaseClass. Metoden AccessProtectedMember i DerivedClass kan komma åt dessa medlemmar. Men om du försöker komma åt skyddade medlemmar utanför klasshierarkin genereras ett kompileringsfel.
Interna medlemmar
Interna medlemmar är tillgängliga inom samma sammansättning. De är inte tillgängliga utanför sammansättningen, även om klassen ärvs.
public class BaseClass
{
internal int internalField;
internal void InternalMethod() { }
}
public class DerivedClass : BaseClass
{
public void AccessInternalMember()
{
internalField = 10;
InternalMethod();
}
}
I det här exemplet ärver DerivedClassinternalField och InternalMethod medlemmar från BaseClass. Metoden AccessInternalMember i DerivedClass kan komma åt dessa medlemmar eftersom de ingår i samma sammansättning. Men om du försöker komma åt interna medlemmar utanför sammansättningen genereras ett kompileringsfel.
Privata medlemmar
Privata medlemmar är endast tillgängliga i den klass där de deklareras. Härledda klasser ärver inte privata medlemmar, så de är inte direkt tillgängliga i den härledda klassen.
public class BaseClass
{
private int privateField;
private void PrivateMethod() { }
}
public class DerivedClass : BaseClass
{
public void AccessPrivateMember()
{
// Can't access privateField or PrivateMethod
}
}
I det här exemplet ärver DerivedClass från BaseClass, men kan inte komma åt privateField eller PrivateMethod medlemmar eftersom de är privata.
Granska användningen av abstrakta, virtuella och förseglade nyckelord i basklassen
Basklasser och härledda klasser använder nyckelorden abstract, virtualoch sealed för att styra beteendet för medlemmar som ärvs. Med de här nyckelorden kan du definiera den kontrollnivå som härledda klasser har över medlemmarna i basklassen.
Granska användningen av nyckelordet abstract
Nyckelordet abstract i C# används för att definiera klasser och klassmedlemmar som är ofullständiga och måste implementeras i härledda klasser. En abstrakt klass kan inte instansieras direkt och är avsedd att vara en basklass för andra klasser. Abstrakta metoder och egenskaper deklareras utan någon implementering och måste åsidosättas i ickeabstract-härledda klasser.
Till exempel:
public abstract class Shape
{
public abstract int GetArea();
}
public class Square : Shape
{
private int _side;
public Square(int side)
{
_side = side;
}
public override int GetArea()
{
return _side * _side;
}
}
class Program
{
static void Main()
{
Square square = new Square(5);
Console.WriteLine($"Area of the square = {square.GetArea()}");
}
}
I det här exemplet är klassen Shape abstrakt och innehåller en abstrakt metod GetArea. Klassen Square ärver från Shape och tillhandahåller en implementering för metoden GetArea. Klassen Square kan instansieras och metoden GetArea returnerar kvadratens yta.
Följande regler beskriver hur nyckelordet abstract påverkar arv:
- Abstrakta klasser: En abstrakt klass kan inte instansieras direkt. Den abstrakta klassen är en basklass för härledda klasser och de härledda klasserna måste tillhandahålla implementeringar för alla abstrakta medlemmar i den abstrakta klassen.
- Abstrakta metoder: Abstrakta metoder deklareras utan någon implementering i den abstrakta klassen. Härledda klasser måste åsidosätta dessa metoder och tillhandahålla implementeringen.
- Abstrakta egenskaper: På samma sätt som abstrakta metoder deklareras abstrakta egenskaper utan implementering och måste åsidosättas i härledda klasser.
Nyckelordet abstract i C# är ett kraftfullt verktyg för att definiera ofullständiga klasser och medlemmar som måste implementeras i härledda klasser. Det framtvingar ett kontrakt som härledda klasser måste följa, vilket säkerställer att vissa metoder och egenskaper implementeras. Lämplig användning av nyckelordet abstract främjar en tydlig avgränsning av ansvar mellan basklasser och härledda klasser.
Granska användningen av nyckelordet virtual
Nyckelordet virtual i C# används för att definiera metoder och egenskaper som kan åsidosättas i härledda klasser. En virtuell metod eller egenskap har en implementering i basklassen, men den kan utökas eller ändras i härledda klasser. Härledda klasser kan åsidosätta virtuella medlemmar för att tillhandahålla sina egna implementeringar.
Till exempel:
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("Animal makes a sound");
}
}
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Dog barks");
}
}
class Program
{
static void Main()
{
Animal animal = new Dog();
animal.MakeSound();
}
}
I det här exemplet definierar klassen Animal en virtuell metod MakeSound som skriver ut ett allmänt meddelande. Klassen Dog ärver från Animal och åsidosätter metoden MakeSound för att skriva ut ett visst meddelande. När du skapar ett Dog-objekt och anropar metoden MakeSound körs den övergripande implementeringen i klassen Dog.
Följande regler beskriver hur nyckelordet virtual påverkar arv:
- Virtuella metoder: En virtuell metod har en implementering i basklassen, men den kan åsidosättas i härledda klasser.
- Virtuella egenskaper: Precis som virtuella metoder har virtuella egenskaper en implementering i basklassen och kan åsidosättas i härledda klasser.
Granska användningen av nyckelordet sealed
Nyckelordet sealed i C# används för att förhindra att en klass- eller klassmedlem ärvs eller åsidosätts. När en klass har markerats som sealedkan den inte användas som basklass för andra klasser. När en metod markeras som sealedkan den inte åsidosättas i härledda klasser.
Till exempel:
public class BaseClass
{
public virtual void Method1()
{
Console.WriteLine("Method1 in BaseClass");
}
public virtual void Method2()
{
Console.WriteLine("Method2 in BaseClass");
}
}
public class DerivedClass : BaseClass
{
public sealed override void Method1()
{
Console.WriteLine("Method1 in DerivedClass");
}
public override void Method2()
{
Console.WriteLine("Method2 in DerivedClass");
}
}
public class FinalClass : DerivedClass
{
// This class can't override Method1 because it's sealed in DerivedClass
public override void Method2()
{
Console.WriteLine("Method2 in FinalClass");
}
}
I det här exemplet ärver DerivedClass från BaseClass och åsidosätter metoden Method1 och markerar den som sealed. Metoden Method2 åsidosättas också i DerivedClass men är inte förseglad.
FinalClass ärver från DerivedClass och försöker åsidosätta metoden Method2. Den kan dock inte åsidosätta metoden Method1 eftersom den är förseglad i DerivedClass.
Följande regler beskriver hur nyckelordet sealed påverkar arv:
- Förseglade klasser: En förseglad klass kan inte användas som basklass för andra klasser. Det förhindrar arv från den förseglade klassen.
- Förseglade metoder: En förseglad metod kan inte åsidosättas i härledda klasser. Det förhindrar ytterligare ändringar av metoden i härledda klasser.
- Förseglade egenskaper: På samma sätt som förseglade metoder kan förseglade egenskaper inte åsidosättas i härledda klasser.
Förseglade klasser och metoder är användbara när du vill förhindra ytterligare tillägg eller ändring av en klass eller metod. De ger ett sätt att begränsa arv och se till att vissa medlemmar förblir oförändrade.
Granska implicit arv från objekt
I C# ärver alla klasser implicit från klassen Object. Klassen Object definierar flera metoder som är tillgängliga för alla klasser, till exempel ToString, Equalsoch GetHashCode. Om en klass inte uttryckligen ärver från en annan klass ärver den fortfarande från Object som standard.
-
ToString: MetodenToStringreturnerar en sträng som representerar det aktuella objektet. Som standard returneras klassens fullständigt kvalificerade namn. -
Equals: MetodenEqualsjämför två objekt för likhet. Som standard jämförs referenserna för objekten. -
GetHashCode: MetodenGetHashCodereturnerar en hash-kod för det aktuella objektet. Som standard returneras hash-koden för objektets referens.
Överväg följande kodexempel som skapar tre Person objekt och visar de ärvda metoderna ToString, Equalsoch GetHashCode:
Person person1 = new Person { Name = "Alice", Age = 30 };
Person person2 = new Person { Name = "Alice", Age = 30 };
Person person3 = person1;
Console.WriteLine(person1.ToString());
Console.WriteLine(person1.Equals(person2));
Console.WriteLine(person1.GetHashCode());
Console.WriteLine(person1.Equals(person3));
public class Person
{
public string? Name { get; set; }
public int Age { get; set; }
}
public class Employee : Person
{
public int EmployeeNumber { get; set; }
public decimal Salary { get; set; }
}
// Output: Person
// False
// 32854180
// True
I det här kodexemplet returnerar metoden ToString det fullständigt kvalificerade namnet på klassen Person, som innehåller det definierade namnområdet. Den första metoden Equals jämför referenserna för objekten person1 och person2 och returnerar False. Metoden GetHashCode returnerar hashkoden för person1-objektets referens. Och sedan jämför Equals-metoden referenserna för person1- och person3-objekten och returnerar True.
Sammanfattning
Arv gör det möjligt för härledda klasser att ärva basklassmedlemmar som definierar en gemensam uppsättning attribut och beteenden. Härledda klasser kan utöka eller ändra beteendet för basklassen genom att lägga till nya medlemmar eller åsidosätta befintliga medlemmar. Nyckelorden abstract, virtualoch sealed används för att styra hur basklassmedlemmar ärvs eller åsidosättas. Synligheten för ärvda medlemmar påverkas av åtkomstmodifierare, till exempel public, protected, internaloch private. Alla klasser i C# ärver implicit från klassen Object, som innehåller flera metoder, till exempel ToString, Equalsoch GetHashCode, som är tillgängliga för alla klasser.