Eigenschappen en methoden in een afgeleide klasse overschrijven

Voltooid

In C# kunt u het trefwoord override gebruiken om het gedrag van de basisklasse in de afgeleide klasse uit te breiden of te wijzigen. Met het trefwoord override kunt u eigenschappen en methoden overschrijven die worden overgenomen van de basisklasse en aangepaste implementaties in de afgeleide klasse bieden. Hiermee kunt u code die is gedefinieerd in de basisklasse opnieuw gebruiken en het gedrag van de basisklasse in de afgeleide klasse uitbreiden of wijzigen.

Als u een eigenschap of methode in een afgeleide klasse wilt overschrijven, moet u deze stappen uitvoeren:

  1. Declareer de leden in de basisklasse als abstract of virtual.
  2. Overschrijf de leden in de afgeleide klasse.
  3. Gebruik desgewenst het base trefwoord om toegang te krijgen tot de basisklasse-implementatie van het overschreven lid in de afgeleide klasse.

Abstracte en virtuele leden van de basisklasse declareren

Voordat u de leden in een afgeleide klasse kunt overschrijven, moet u de leden in de basisklasse declareren als abstract of virtual.

  • Abstract: Het trefwoord abstract geeft aan dat het lid geen implementatie heeft en moet worden overschreven in een afgeleide klasse.
  • Virtueel: Het trefwoord virtual geeft aan dat het lid een implementatie heeft, maar kan worden overschreven of uitgebreid in een afgeleide klasse.

In het volgende voorbeeld ziet u hoe u abstracte en virtuele leden in een basisklasse declareert:


public class BaseClass
{
    public string Property1 { get; set; } = "Base - Property1";
    public string Property2 { get; set; } = "Base - Property2";

    public virtual void Method1()
    {
        Console.WriteLine("Base - Method1");
    }

    public void Method2()
    {
        Console.WriteLine("Base - Method2");
    }
}

Leden in de afgeleide klasse overschrijven

Nadat u de leden in de basisklasse hebt declareren als abstract of virtual, kunt u de leden in de afgeleide klasse overschrijven met behulp van het trefwoord override. Het override trefwoord geeft aan dat het lid in de afgeleide klasse het lid in de basisklasse overschrijft.

Bekijk het volgende voorbeeld:


// Step 1: Create instances of the base class and the derived classes
BaseClass baseClass = new BaseClass();
DerivedClass derivedClass = new DerivedClass();
BaseClass baseClassReferencingDerivedClass = new DerivedClass();

// Step 2: Access properties and methods of the base class
Console.WriteLine($"\n{baseClass.Property1}");
Console.WriteLine($"{baseClass.Property2}");
baseClass.Method1();
baseClass.Method2();

// Step 3: Access properties and methods of the derived class
Console.WriteLine($"\n{derivedClass.Property1}");
Console.WriteLine($"{derivedClass.Property2}");
derivedClass.Method1();
derivedClass.Method2();

// Step 4: Access properties and methods of the base class that references the derived class
Console.WriteLine($"\n{baseClassReferencingDerivedClass.Property1}");
Console.WriteLine($"{baseClassReferencingDerivedClass.Property2}");
baseClassReferencingDerivedClass.Method1();
baseClassReferencingDerivedClass.Method2();

/*Output:
Base - Property1
Base - Property2
Base - Method1
Base - Method2

Derived - Property1
Derived - Property2
Derived - Method1
Derived - Method2

Derived - Property1
Base - Property2
Derived - Method1
Base - Method2
*/

public class BaseClass
{
    public virtual string Property1 { get; set; } = "Base - Property1";
    public virtual string Property2 { get; set; } = "Base - Property2";

    public virtual void Method1()
    {
        Console.WriteLine("Base - Method1");
    }

    public void Method2()
    {
        Console.WriteLine("Base - Method2");
    }
}

public class DerivedClass : BaseClass
{
    public override string Property1 { get; set; } = "Derived - Property1";
    public new string Property2 { get; set; } = "Derived - Property2";

    public override void Method1()
    {
        Console.WriteLine("Derived - Method1");
    }

    public new void Method2()
    {
        Console.WriteLine("Derived - Method2");
    }
}

Deze code laat zien hoe u eigenschappen en methoden in een afgeleide klasse wijzigt en verbergt met behulp van de override en new trefwoorden. De code definieert een basisklasse (BaseClass) en een afgeleide klasse (DerivedClass) die wordt overgenomen van de basisklasse. De basisklasse heeft twee eigenschappen (Eigenschap1 en Eigenschap2) en twee methoden (Method1 en Method2). De afgeleide klasse overschrijft Property1 en Method1 en verbergt Property2 en Method2 met behulp van het trefwoord new.

Hier volgt een uitsplitsing van de code:

  1. In stap 1 maakt de code een exemplaar van de basisklasse (baseClass), een exemplaar van de afgeleide klasse (derivedClass) en een exemplaar van de afgeleide klasse waarnaar wordt verwezen door een basisklassevariabele (baseClassReferencingDerivedClass). Het baseClassReferencingDerivedClass exemplaar demonstreert polymorfisme, waarbij een basisklasseverwijzing verwijst naar een afgeleid klasseobject.

  2. In stap 2 opent en drukt de code de eigenschappen en methoden van het basisklasse-exemplaar af. Aangezien baseClass een exemplaar van BaseClassis, worden de eigenschappen en methoden gebruikt die zijn gedefinieerd in BaseClass. De uitvoer toont de waarden en het gedrag zoals gedefinieerd in de basisklasse.

  3. In stap 3 opent en drukt de code de eigenschappen en methoden van het afgeleide klasse-exemplaar af. Aangezien derivedClass een exemplaar van DerivedClassis, worden de overschreven eigenschappen en methoden gebruikt die zijn gedefinieerd in DerivedClass. De uitvoer weerspiegelt de waarden en het gedrag zoals gedefinieerd in de afgeleide klasse.

  4. In stap 4 opent en drukt de code de eigenschappen en methoden van het afgeleide klasse-exemplaar af waarnaar wordt verwezen door een basisklassevariabele. Voor eigenschappen en methoden die worden overschreven (Property1 en Method1), wordt de implementatie van de afgeleide klasse gebruikt. Voor eigenschappen en methoden die zijn verborgen (Property2 en Method2), wordt de basisklasse-implementatie echter gebruikt. Dit toont het verschil tussen het overschrijven van methoden (met behulp van override) en het verbergen van methoden (met behulp van new).

Een abstracte basisklasse definiëren

Wanneer u een basisklasse definieert als abstract, geeft u aan dat de klasse onvolledig is en moet worden geïmplementeerd door afgeleide klassen. Abstracte klassen kunnen abstracte eigenschappen en methoden bevatten die moeten worden geïmplementeerd door afgeleide klassen. Abstracte basisklassen kunnen niet rechtstreeks worden geïnstantieerd, dus ze worden gebruikt als sjabloon voor afgeleide klassen om de abstracte leden te implementeren.

Bekijk het volgende voorbeeld:


// create instances of the base class and the derived classes
// Note: We can't create an instance of an abstract class
// BaseClass baseClass = new BaseClass(); // This line would cause a compile-time error
DerivedClass derivedClass = new DerivedClass();
BaseClass baseClassReferencingDerivedClass = new DerivedClass();

// access properties and methods of the derived class
Console.WriteLine($"\n{derivedClass.Property1}");
Console.WriteLine($"{derivedClass.Property2}");
derivedClass.Method1();
derivedClass.Method2();

// access properties and methods of the base class that references the derived class
Console.WriteLine($"\n{baseClassReferencingDerivedClass.Property1}");
Console.WriteLine($"{baseClassReferencingDerivedClass.Property2}");
baseClassReferencingDerivedClass.Method1();
baseClassReferencingDerivedClass.Method2();

/*Output:
Derived - Property1
Derived - Property2
Derived - Method1
Derived - Method2

Derived - Property1
Base - Property2
Derived - Method1
Base - Method2
*/

public abstract class BaseClass
{
    public abstract string Property1 { get; set; }
    public virtual string Property2 { get; set; } = "Base - Property2";

    public abstract void Method1();

    public void Method2()
    {
        Console.WriteLine("Base - Method2");
    }
}

public class DerivedClass : BaseClass
{
    public override string Property1 { get; set; } = "Derived - Property1";
    public new string Property2 { get; set; } = "Derived - Property2";

    public override void Method1()
    {
        Console.WriteLine("Derived - Method1");
    }

    public new void Method2()
    {
        Console.WriteLine("Derived - Method2");
    }
}

Wanneer de basisklasse wordt gedeclareerd met behulp van het trefwoord abstract, kan de basisklasse niet rechtstreeks worden geïnstantieerd. In plaats daarvan moet u exemplaren maken van de afgeleide klassen waarmee de abstracte leden worden geïmplementeerd. De afgeleide klasse moet implementaties bieden voor de abstracte leden die zijn gedefinieerd in de basisklasse. Leden die niet abstract zijn, kunnen worden overschreven of verborgen in de afgeleide klasse.

Impliciet overgenomen leden van de objectklasse overschrijven

Alle klassen in C# nemen impliciet over van de Object-klasse. De Object-klasse definieert verschillende leden die worden overgenomen door alle klassen, zoals ToString, Equalsen GetHashCode. U kunt deze leden in uw klassen overschrijven om aangepaste implementaties te bieden.

Bekijk het volgende voorbeeld:


// create instances of the derived classes
DerivedClass1 derivedClass1 = new DerivedClass1();
DerivedClass2 derivedClass2a = new DerivedClass2 { Property1 = "Value1", Property2 = "Value2" };
DerivedClass2 derivedClass2b = new DerivedClass2 { Property1 = "Value1", Property2 = "Value2" };
DerivedClass2 derivedClass2c = new DerivedClass2 { Property1 = "Value3", Property2 = "Value4" };

// demonstrate Object class methods for DerivedClass1
Console.WriteLine("\nDemonstrating Object class methods for DerivedClass1:");
Console.WriteLine($"ToString: {derivedClass1.ToString()}");
Console.WriteLine($"Equals: {derivedClass1.Equals(new DerivedClass1())}");
Console.WriteLine($"GetHashCode: {derivedClass1.GetHashCode()}");

// demonstrate overridden Object class methods for DerivedClass2
Console.WriteLine("\nDemonstrating overridden Object class methods for DerivedClass2:");
Console.WriteLine($"ToString: {derivedClass2a.ToString()}");
Console.WriteLine($"Equals (derivedClass2a vs derivedClass2b): {derivedClass2a.Equals(derivedClass2b)}"); // should return true
Console.WriteLine($"Equals (derivedClass2a vs derivedClass2c): {derivedClass2a.Equals(derivedClass2c)}"); // should return false
Console.WriteLine($"GetHashCode (derivedClass2a): {derivedClass2a.GetHashCode()}");
Console.WriteLine($"GetHashCode (derivedClass2b): {derivedClass2b.GetHashCode()}");
Console.WriteLine($"GetHashCode (derivedClass2c): {derivedClass2c.GetHashCode()}");

/*Output:
Demonstrating Object class methods for DerivedClass1:
ToString: DerivedClass1
Equals: False
GetHashCode: [HashCode]

Demonstrating overridden Object class methods for DerivedClass2:
ToString: DerivedClass2: Property1 = Value1, Property2 = Value2
Equals (derivedClass2a vs derivedClass2b): True
Equals (derivedClass2a vs derivedClass2c): False
GetHashCode (derivedClass2a): [HashCode]
GetHashCode (derivedClass2b): [HashCode]
GetHashCode (derivedClass2c): [HashCode]
*/

public abstract class BaseClass
{
    public abstract string Property1 { get; set; }
    public virtual string Property2 { get; set; } = "Base - Property2";

    public abstract void Method1();

    public void Method2()
    {
        Console.WriteLine("Base - Method2");
    }
}

public class DerivedClass1 : BaseClass
{
    public override string Property1 { get; set; } = "Derived1 - Property1";
    public new string Property2 { get; set; } = "Derived1 - Property2";

    public override void Method1()
    {
        Console.WriteLine("Derived1 - Method1");
    }

    public new void Method2()
    {
        Console.WriteLine("Derived1 - Method2");
    }
}

public class DerivedClass2 : BaseClass
{
    public override string Property1 { get; set; } = "Derived2 - Property1";
    public new string Property2 { get; set; } = "Derived2 - Property2";

    public override void Method1()
    {
        Console.WriteLine("Derived2 - Method1");
    }

    public new void Method2()
    {
        Console.WriteLine("Derived2 - Method2");
    }

    // Override ToString method
    public override string ToString()
    {
        return $"DerivedClass2: Property1 = {Property1}, Property2 = {Property2}";
    }

    // Override Equals method
    public override bool Equals(object obj)
    {
        if (obj is DerivedClass2 other)
        {
            return Property1 == other.Property1 && Property2 == other.Property2;
        }
        return false;
    }

    // Override GetHashCode method
    public override int GetHashCode()
    {
        return HashCode.Combine(Property1, Property2);
    }
}

In dit voorbeeld nemen de klassen DerivedClass1 en DerivedClass2 over van de BaseClass-klasse. De DerivedClass2 klasse overschrijft de ToString, Equalsen GetHashCode methoden die zijn overgenomen van de Object-klasse. De ToString methode retourneert een tekenreeksweergave van het object, de Equals methode vergelijkt twee objecten voor gelijkheid en de GetHashCode methode retourneert een hash-code voor het object. De DerivedClass2-klasse biedt aangepaste implementaties voor deze methoden om de eigenschappen van het object weer te geven en objecten te vergelijken op basis van hun eigenschappen.

Samenvatting

Door eigenschappen en methoden in een afgeleide klasse te overschrijven, kunt u het gedrag van de basisklasse uitbreiden of wijzigen. Met behulp van het trefwoord override kunt u aangepaste implementaties opgeven voor eigenschappen en methoden die worden overgenomen van de basisklasse. Hiermee kunt u code die is gedefinieerd in de basisklasse opnieuw gebruiken en het gedrag van de basisklasse in de afgeleide klasse uitbreiden of wijzigen. U kunt ook het new trefwoord gebruiken om eigenschappen en methoden in de basisklasse te verbergen en nieuwe implementaties in de afgeleide klasse te bieden.