Untuk antarmuka, penambahan abstract
, atau bahkan public
kata kunci akan menjadi mubazir, jadi Anda menghilangkannya:
interface MyInterface {
void Method();
}
Di CIL, metode ini ditandai virtual
dan abstract
.
(Perhatikan bahwa Java memungkinkan anggota antarmuka untuk dideklarasikan public abstract
).
Untuk kelas pelaksana, ada beberapa opsi:
Non-overridable : Dalam C # kelas tidak mendeklarasikan metode sebagai virtual
. Artinya, kelas tersebut tidak dapat diganti dalam kelas turunan (hanya tersembunyi). Dalam CIL, metode ini masih virtual (tetapi disegel) karena harus mendukung polimorfisme terkait tipe antarmuka.
class MyClass : MyInterface {
public void Method() {}
}
Dapat diganti : Baik di C # dan di CIL metodenya adalah virtual
. Ini berpartisipasi dalam pengiriman polimorfik dan dapat diganti.
class MyClass : MyInterface {
public virtual void Method() {}
}
Eksplisit : Ini adalah cara kelas untuk mengimplementasikan antarmuka tetapi tidak menyediakan metode antarmuka dalam antarmuka publik dari kelas itu sendiri. Dalam CIL, metode ini akan menjadi private
(!) Tetapi masih dapat dipanggil dari luar kelas dari referensi ke tipe antarmuka yang sesuai. Implementasi eksplisit juga tidak bisa diganti. Ini dimungkinkan karena ada direktif CIL ( .override
) yang akan menghubungkan metode privat ke metode antarmuka terkait yang diimplementasikannya.
[C #]
class MyClass : MyInterface {
void MyInterface.Method() {}
}
[CIL]
.method private hidebysig newslot virtual final instance void MyInterface.Method() cil managed
{
.override MyInterface::Method
}
Di VB.NET, Anda bahkan dapat membuat alias nama metode antarmuka di kelas implementasi.
[VB.NET]
Public Class MyClass
Implements MyInterface
Public Sub AliasedMethod() Implements MyInterface.Method
End Sub
End Class
[CIL]
.method public newslot virtual final instance void AliasedMethod() cil managed
{
.override MyInterface::Method
}
Sekarang, pertimbangkan kasus aneh ini:
interface MyInterface {
void Method();
}
class Base {
public void Method();
}
class Derived : Base, MyInterface { }
Jika Base
dan Derived
dideklarasikan dalam perakitan yang sama, kompilator akan membuat Base::Method
virtual dan tertutup (dalam CIL), meskipun Base
antarmuka tidak mengimplementasikan.
Jika Base
dan Derived
berada dalam rakitan yang berbeda, saat mengompilasi Derived
rakitan, kompilator tidak akan mengubah rakitan lain, jadi ia akan memperkenalkan anggota di dalamnya Derived
yang akan menjadi implementasi eksplisit MyInterface::Method
yang hanya akan mendelegasikan panggilan ke Base::Method
.
Jadi Anda lihat, setiap implementasi metode antarmuka harus mendukung perilaku polimorfik, dan dengan demikian harus ditandai virtual pada CIL, bahkan jika kompilator harus melalui rintangan untuk melakukannya.
Ya, metode implementasi antarmuka adalah virtual sejauh menyangkut waktu proses. Ini adalah detail implementasi, itu membuat antarmuka berfungsi. Metode virtual mendapatkan slot di kelas 'v-table, setiap slot memiliki penunjuk ke salah satu metode virtual. Mentransmisikan objek ke jenis antarmuka menghasilkan penunjuk ke bagian tabel yang mengimplementasikan metode antarmuka. Kode klien yang menggunakan referensi antarmuka sekarang melihat penunjuk metode antarmuka pertama di offset 0 dari penunjuk antarmuka, dan sebagainya.
Apa yang kurang saya hargai dalam jawaban asli saya adalah pentingnya atribut terakhir . Ini mencegah kelas turunan menimpa metode virtual. Kelas turunan harus mengimplementasikan ulang antarmuka, metode implementasi membayangi metode kelas dasar. Yang cukup untuk mengimplementasikan kontrak bahasa C # yang mengatakan bahwa metode implementasi tidak virtual.
Jika Anda mendeklarasikan metode Dispose () di kelas Contoh sebagai virtual, Anda akan melihat atribut terakhir dihapus. Sekarang mengizinkan kelas turunan untuk menimpanya.
sumber
Di sebagian besar lingkungan kode terkompilasi lainnya, antarmuka diimplementasikan sebagai vtable - daftar pointer ke badan metode. Biasanya sebuah kelas yang mengimplementasikan banyak antarmuka akan memiliki suatu tempat di kompiler internalnya yang menghasilkan metadata daftar vtables antarmuka, satu vtable per antarmuka (sehingga urutan metode dipertahankan). Ini adalah bagaimana antarmuka COM biasanya diimplementasikan juga.
Dalam .NET, antarmuka tidak diimplementasikan sebagai vtabel berbeda untuk setiap kelas. Metode antarmuka diindeks melalui tabel metode antarmuka global yang semua antarmuka menjadi bagiannya. Oleh karena itu, tidak perlu mendeklarasikan metode virtual agar metode tersebut dapat mengimplementasikan metode antarmuka - tabel metode antarmuka global dapat langsung menunjuk ke alamat kode metode kelas.
Mendeklarasikan metode virtual untuk mengimplementasikan antarmuka juga tidak diperlukan dalam bahasa lain, bahkan dalam platform non-CLR. Bahasa Delphi di Win32 adalah salah satu contohnya.
sumber
Mereka tidak virtual (dalam hal bagaimana kami memikirkannya, jika tidak dalam hal implementasi yang mendasarinya sebagai (virtual tersegel) - bagus untuk membaca jawaban lain di sini dan belajar sesuatu sendiri :-)
Mereka tidak menimpa apa pun - tidak ada implementasi di antarmuka.
Semua antarmuka menyediakan "kontrak" yang harus dipatuhi kelas - pola, jika Anda suka, sehingga pemanggil tahu cara memanggil objek meskipun mereka belum pernah melihat kelas tertentu sebelumnya.
Terserah kelas untuk kemudian mengimplementasikan metode antarmuka sebagaimana mestinya, dalam batasan kontrak - virtual atau "non-virtual" (ternyata virtual tertutup).
sumber
Antarmuka adalah konsep yang lebih abstrak daripada kelas, ketika Anda mendeklarasikan kelas yang mengimplementasikan antarmuka, Anda hanya mengatakan "kelas harus memiliki metode khusus ini dari antarmuka, dan tidak masalah apakah statis , virtual , non virtual , diganti , sebagai asalkan memiliki ID yang sama dan parameter jenis yang sama ".
Bahasa lain yang mendukung antarmuka seperti Object Pascal ("Delphi") dan Objective-C (Mac) tidak memerlukan metode antarmuka untuk ditandai virtual dan bukan virtual, baik.
Namun, Anda mungkin benar, menurut saya mungkin ide yang baik untuk memiliki atribut "virtual" / "override" tertentu di antarmuka, jika Anda ingin membatasi metode kelas yang mengimplementasikan antarmuka tertentu. Namun, itu juga berarti memiliki kata kunci "nonvirtual", "dontcareifvirtualornot", untuk kedua antarmuka.
Saya memahami pertanyaan Anda, karena saya melihat sesuatu yang serupa di Java, ketika metode kelas harus menggunakan "@virtual" atau "@override" untuk memastikan bahwa suatu metode dimaksudkan untuk menjadi virtual.
sumber
override
adalah kata kunci kelas satu dalam bahasa itu sendiri.