Bagikan melalui


Penerapan versi dengan Penimpaan dan Kata Kunci Baru (Panduan Pemrograman C#)

Bahasa C# dirancang agar pengembangan versi antara kelas dasar dan turunan dalam pustaka yang berbeda dapat berevolusi dan mempertahankan kompatibilitas mundur. Ini berarti, misalnya, bahwa pengenalan anggota baru di kelas dasar dengan nama yang sama dengan anggota di kelas turunan sepenuhnya didukung oleh C# dan tidak menyebabkan perilaku yang tidak terduga. Ini juga berarti bahwa kelas harus secara eksplisit menyatakan apakah metode dimaksudkan untuk mengambil alih metode yang diwariskan, atau apakah metode adalah metode baru yang menyembunyikan metode bernama serupa yang diwariskan.

Dalam C#, kelas turunan dapat berisi metode dengan nama yang sama dengan metode kelas dasar.

  • Jika metode di kelas turunan tidak didahului oleh kata kunci new atau override, pengompilasi akan mengeluarkan peringatan dan metode akan berperilaku seolah-olah new kata kunci tersebut terdapat.

  • Jika metode di kelas turunan didahului dengan new kata kunci, metode didefinisikan sebagai independen dari metode di kelas dasar.

  • Jika metode di kelas turunan didahului dengan override kata kunci, objek kelas turunan akan memanggil metode tersebut alih-alih metode kelas dasar.

  • Untuk menerapkan override kata kunci ke metode di kelas turunan, metode kelas dasar harus ditentukan virtual.

  • Metode kelas dasar dapat dipanggil dari dalam kelas turunan base menggunakan kata kunci.

  • Kata kunci override, virtual, dan new juga dapat diterapkan ke properti, pengindeks, dan peristiwa.

Secara default, metode C# tidak virtual. Jika metode dinyatakan sebagai virtual, kelas apa pun yang mewarisi metode dapat menerapkan versinya sendiri. Untuk membuat metode virtual, pengubah virtual digunakan dalam deklarasi metode kelas dasar. Kelas turunan kemudian dapat mengambil alih metode virtual dasar dengan menggunakan override kata kunci atau menyembunyikan metode virtual di kelas dasar dengan menggunakan new kata kunci. Jika baik kata kunci override maupun kata kunci new tidak ditentukan, pengkompilasi akan mengeluarkan peringatan dan metode dalam kelas turunan akan menyembunyikan metode dalam kelas dasar.

Untuk menunjukkan hal ini dalam praktiknya, asumsikan sejenak bahwa Perusahaan A telah membuat kelas bernama GraphicsClass, yang digunakan program Anda. Berikut ini adalah GraphicsClass:

class GraphicsClass
{
    public virtual void DrawLine() { }
    public virtual void DrawPoint() { }
}

Perusahaan Anda menggunakan kelas ini, dan Anda menggunakannya untuk mendapatkan kelas Anda sendiri, menambahkan metode baru:

class YourDerivedGraphicsClass : GraphicsClass
{
    public void DrawRectangle() { }
}

Aplikasi Anda digunakan tanpa masalah, hingga Perusahaan A merilis versi GraphicsClassbaru , yang menyerupai kode berikut:

class GraphicsClass
{
    public virtual void DrawLine() { }
    public virtual void DrawPoint() { }
    public virtual void DrawRectangle() { }
}

Versi GraphicsClass baru sekarang berisi metode bernama DrawRectangle. Awalnya, tidak ada yang terjadi. Versi baru masih kompatibel secara biner dengan versi lama. Perangkat lunak apa pun yang telah Anda sebarkan akan terus berfungsi, bahkan jika kelas baru diinstal pada sistem komputer tersebut. Setiap pemanggilan yang ada ke metode DrawRectangle akan terus merujuk ke versi Anda di kelas turunan Anda.

Namun, segera setelah Anda mengkompilasi ulang aplikasi Anda dengan menggunakan versi GraphicsClassbaru , Anda akan menerima peringatan dari pengkompilasi, CS0108. Peringatan ini memberi tahu Anda bahwa Anda harus mempertimbangkan bagaimana Anda ingin metode Anda DrawRectangle berfungsi dalam aplikasi Anda.

Jika Anda ingin metode Anda mengambil alih metode kelas dasar baru, gunakan override kata kunci:

class YourDerivedGraphicsClass : GraphicsClass
{
    public override void DrawRectangle() { }
}

Kata override kunci memastikan bahwa setiap objek yang berasal dari YourDerivedGraphicsClass akan menggunakan versi kelas turunan dari DrawRectangle. Objek yang berasal dari YourDerivedGraphicsClass masih dapat mengakses versi kelas dasar dengan DrawRectangle menggunakan kata kunci dasar:

base.DrawRectangle();

Jika Anda tidak ingin metode Anda mengambil alih metode kelas dasar baru, pertimbangan berikut berlaku. Untuk menghindari kebingungan antara kedua metode, Anda dapat mengganti nama metode Anda. Ini bisa memakan waktu dan rawan kesalahan, dan hanya tidak praktis dalam beberapa kasus. Namun, jika proyek Anda relatif kecil, Anda dapat menggunakan opsi Pemfaktoran Ulang Visual Studio untuk mengganti nama metode. Untuk informasi selengkapnya, lihat Merefaktor Kelas dan Jenis (Perancang Kelas).

Atau, Anda dapat mencegah peringatan dengan menggunakan kata kunci new dalam definisi kelas turunan Anda:

class YourDerivedGraphicsClass : GraphicsClass
{
    public new void DrawRectangle() { }
}

new Menggunakan kata kunci memberi tahu pengkompilasi bahwa definisi Anda menyembunyikan definisi yang terkandung dalam kelas dasar. Ini adalah perilaku default.

Ambil alih dan Pilihan Metode

Ketika metode dinamai pada kelas, pengkompilasi C# memilih metode terbaik untuk memanggil jika lebih dari satu metode kompatibel dengan panggilan, seperti ketika ada dua metode dengan nama yang sama, dan parameter yang kompatibel dengan parameter yang diteruskan. Metode berikut akan kompatibel:

public class Derived : Base
{
    public override void DoWork(int param) { }
    public void DoWork(double param) { }
}

Ketika DoWork dipanggil pada instans Derived, pengkompilasi C# pertama-tama akan mencoba membuat panggilan kompatibel dengan versi DoWork yang dideklarasikan awalnya pada Derived. Metode override tidak dianggap sebagai yang dinyatakan pada kelas, melainkan merupakan implementasi baru dari metode yang dideklarasikan pada kelas dasar. Hanya jika compiler C# tidak dapat mencocokkan panggilan metode ke metode asli pada Derived, ia akan mencoba mencocokkan panggilan ke metode yang diubah dengan nama yang sama dan parameter yang kompatibel. Contohnya:

int val = 5;
Derived d = new();
d.DoWork(val);  // Calls DoWork(double).

Karena variabel val dapat dikonversi ke tipe data double secara implisit, pengkompilasi C# memanggil DoWork(double) alih-alih DoWork(int). Ada dua cara untuk menghindari hal ini. Pertama, hindari mendeklarasikan metode baru dengan nama yang sama dengan metode virtual. Kedua, Anda dapat menginstruksikan pengkompilasi C# untuk memanggil metode virtual dengan membuatnya mencari daftar metode kelas dasar dengan mentransmisikan instans Derived ke Base. Karena metodenya virtual, implementasi DoWork(int) pada Derived akan dipanggil. Contohnya:

((Base)d).DoWork(val);  // Calls DoWork(int) on Derived.

Untuk lebih banyak contoh new dan override, lihat Mengetahui Kapan Menggunakan Override dan Kata Kunci Baru.

Lihat juga