Mengakses anggota kelas dasar dari kelas turunan

Selesai

Kelas turunan yang menggantikan atau mengambil alih metode atau properti kelas dasar masih dapat mengakses metode atau properti pada kelas dasar dengan menggunakan kata kunci base. Ini memungkinkan Anda untuk memanggil konstruktor kelas dasar, metode, dan properti dari anggota yang ditimpa dari kelas turunan. Dengan menggunakan kata kunci base, Anda dapat memastikan bahwa kelas turunan menggunakan kembali dengan benar dan memperluas fungsionalitas yang disediakan oleh kelas dasar.

Kata kunci base digunakan untuk menyelesaikan tugas berikut:

  • Untuk memanggil metode kelas dasar dari metode penimpaan kelas turunan.
  • Untuk mengimplementasikan konstruktor kelas dasar dari dalam konstruktor kelas turunan.

Kata kunci base memiliki batasan berikut:

  • Kata kunci base hanya dapat digunakan dalam konstruktor, metode instans, atau aksesor properti instans.
  • Kata kunci base tidak dapat digunakan dalam metode statis. Mencoba menggunakan kata kunci base dalam metode statis akan menghasilkan kesalahan.

Saat Anda menerapkan kata kunci base di kelas turunan, kode Anda menggunakan kelas dasar yang ditentukan dalam deklarasi kelas. Misalnya, jika Anda menentukan ClassC : ClassB kelas dalam deklarasi kelas, kata kunci base memungkinkan kode Anda mengakses anggota ClassB dari ClassC. Tidak masalah apakah kelas ClassB mewarisi dari kelas ClassA.

Mengakses properti dan metode kelas dasar dari kelas turunan

Mengakses properti dan metode kelas dasar dari kelas turunan adalah persyaratan umum saat menerapkan warisan. Kode berikut menunjukkan sintaks untuk menerapkan kata kunci base:

base.MemberName

Perhatikan bahwa kata kunci base dan nama anggota kelas dasar dipisahkan oleh titik (.). MemberName dapat menjadi properti, metode, atau bidang kelas dasar.

Kode berikut menunjukkan cara mengakses properti dan metode kelas dasar dari kelas turunan:


// 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;
    }
}

Dalam sampel kode ini, kelas DerivedClass1 mewarisi dari BaseClass dan mengambil alih metodenya untuk memperluas fungsionalitasnya. Kode mengimplementasikan langkah-langkah berikut:

  1. Instans DerivedClass1 dibuat menggunakan pernyataan DerivedClass1 derivedClass1 = new DerivedClass1();. Instans kelas turunan ini digunakan untuk memanggil dan menunjukkan metode penggantian kelas turunan.

  2. Kode memanggil Method1 kelas turunan dari dalam pernyataan Console.WriteLine. Fungsi yang ditimpa Method1 tidak dapat mengakses abstrak Method1 dari kelas dasar. Sebaliknya, ia menyediakan implementasinya sendiri yang mengembalikan string yang menunjukkan bahwa string tersebut unik untuk kelas turunan.

  3. Kode memanggil Method2 kelas turunan. Method2 yang ditimpa menggunakan base.Method2 untuk menggunakan kembali implementasi Method2 kelas dasar. Metode ini mengakses Property2 kelas dasar dan mencetak nilainya. Metode yang ditimpa kemudian menggunakan nilai Boolean yang dikembalikan oleh Method2 kelas dasar dan nilai Property2, untuk memperluas fungsionalitas Method2 atau mengimplementasikan perilaku alternatif. Langkah ini menunjukkan bagaimana kelas turunan dapat dibangun dan memodifikasi perilaku metode kelas dasar.

Nota

Praktik terbaik bagi anggota virtual menggunakan base untuk memanggil implementasi kelas dasar anggota tersebut dalam implementasi mereka sendiri. Membiarkan perilaku kelas dasar terjadi memungkinkan kelas turunan untuk berkonsentrasi pada penerapan perilaku khusus untuk kelas turunan. Jika implementasi kelas dasar tidak dipanggil, terserah kelas turunan untuk membuat perilaku mereka kompatibel dengan perilaku kelas dasar.

Konstruktor kelas dasar akses dari kelas turunan

Konstruktor kelas di kelas dasar dapat diakses dari konstruktor kelas turunan dengan menggunakan kata kunci base.

Kode berikut menunjukkan cara mengakses konstruktor kelas dasar dari kelas turunan:


// 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;
    }
}

Memanggil konstruktor kelas dasar dari konstruktor kelas turunan adalah penting. Misalnya, ketika konstruktor kelas dasar menginisialisasi properti umum yang digunakan oleh kelas turunan. Dengan memanggil konstruktor kelas dasar dari konstruktor kelas turunan, Anda memastikan bahwa properti umum diinisialisasi sebelum konstruktor kelas turunan dijalankan.

Pertimbangkan kode berikut:


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();
    }
}

Perhatikan bahwa konstruktor kelas Car memanggil konstruktor kelas dasar menggunakan kata kunci base. Memanggil konstruktor kelas dasar terlebih dahulu memastikan bahwa properti Speed dan Fuel kelas dasar Vehicle diinisialisasi dengan benar sebelum konstruktor kelas Car dijalankan. Urutan peristiwa ini penting karena properti TrunkCapacity kelas Car diinisialisasi menggunakan properti Speed dan Fuel dari kelas dasar Vehicle.

Ringkasan

Pertimbangkan panduan berikut saat mengakses anggota kelas dasar dari kelas turunan:

  • Gunakan kata kunci base untuk mengakses anggota kelas dasar dari kelas turunan.
  • Gunakan kata kunci base untuk memanggil konstruktor kelas dasar dari konstruktor kelas turunan.
  • Gunakan kata kunci base untuk mengakses bidang kelas dasar, properti, dan metode dari metode yang ditimpa dalam kelas turunan.