Bagaimana Go meningkatkan produktivitas dengan antarmuka "implisit", dan bagaimana hal itu dibandingkan dengan gagasan C # tentang Metode Penyuluhan?

21

Dalam Go Language Tutorial, mereka menjelaskan cara kerja antarmuka:

Go tidak memiliki kelas. Namun, Anda dapat menentukan metode pada tipe struct. The Metode penerima muncul dalam daftar argumen sendiri antara kata kunci func dan nama metode.

type Vertex struct {
    X, Y float64
}

func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

Jenis antarmuka didefinisikan oleh serangkaian metode. Nilai tipe antarmuka dapat menampung nilai apa pun yang mengimplementasikan metode tersebut.

Ini adalah satu-satunya cara untuk membuat antarmuka di Go. Google selanjutnya menjelaskan bahwa:

Tipe mengimplementasikan antarmuka dengan mengimplementasikan metode. Tidak ada deklarasi niat yang eksplisit [yaitu interfacedeklarasi].

Antarmuka implisit memisahkan paket implementasi dari paket yang mendefinisikan antarmuka: tidak tergantung pada yang lain.

Ini juga mendorong definisi antarmuka yang tepat, karena Anda tidak harus menemukan setiap implementasi dan menandainya dengan nama antarmuka yang baru.

Semua ini kedengarannya mencurigakan seperti Metode Ekstensi dalam C # , kecuali bahwa metode dalam Go adalah polimorfik tanpa ampun; mereka akan beroperasi pada semua jenis yang mengimplementasikannya.

Google mengklaim bahwa ini mendorong perkembangan yang cepat, tetapi mengapa? Apakah Anda melepaskan sesuatu dengan menjauh dari antarmuka eksplisit di C #? Bisakah Metode Ekstensi dalam C # memungkinkan seseorang untuk mendapatkan beberapa manfaat yang dimiliki antarmuka Go di C #?

Robert Harvey
sumber
Terkait: stackoverflow.com/q/11441905
Robert Harvey
1
Antarmuka Go ini terdengar lebih seperti yang dapat dilakukan templat C ++ daripada metode ekstensi C #. Di C # tidak ada yang seperti "jenis apa pun yang mengimplementasikan metode A dan B", tetapi Anda bisa melakukannya dengan menggunakan templat C ++.
svick
Terkait: codeproject.com/Articles/9281/…
Robert Harvey
Bukankah 'interface implisit' hanya bentuk mengetik bebek?
Allon Guralnek
"Bukankah 'antarmuka implisit' hanya bentuk pengetikan bebek?" Antarmuka Go adalah contoh pengetikan struktural. Konsep yang sangat mirip.
mortdeus

Jawaban:

12

Saya tidak melihat metode ekstensi dan antarmuka implisit sebagai sama sekali.

Pertama mari kita bicara dengan tujuan.

Metode ekstensi ada sebagai gula sintaksis khusus untuk memberi Anda kemampuan untuk menggunakan metode seolah-olah itu anggota suatu objek, tanpa memiliki akses ke internal objek itu. Tanpa metode ekstensi Anda dapat melakukan hal yang persis sama, Anda hanya tidak mendapatkan sintaks yang menyenangkan someObjectYouCantChange.YourMethod()dan lebih baik harus menelepon YourMethod(someObjectYouCantChange).

Tujuan dari antarmuka implisit adalah agar Anda dapat mengimplementasikan antarmuka pada objek yang tidak dapat Anda akses untuk berubah. Ini memberi Anda kemampuan untuk membuat hubungan polimorfik antara objek apa pun yang Anda tulis sendiri dan objek apa pun yang tidak memiliki akses ke internal.

Sekarang mari kita bicara konsekuensi.

Metode ekstensi benar-benar tidak punya, ini sangat sejalan dengan kendala keamanan yang kejam. NET mencoba untuk membantu dalam perspektif yang berbeda pada model (perspektif dari dalam, luar, pewaris, dan tetangga). Konsekuensinya hanyalah beberapa kesenangan sintaksis.

Konsekuensi dari antarmuka implisit adalah beberapa hal.

  • Implementasi antarmuka yang tidak disengaja, ini bisa merupakan kecelakaan bahagia, atau pelanggaran LSP yang tidak disengaja dengan bertemu dengan antarmuka orang lain yang tidak Anda maksudkan tanpa menghormati maksud kontraknya.
  • Kemampuan untuk dengan mudah membuat metode apa pun menerima tiruan dari objek yang diberikan sama sekali dengan hanya mencerminkan antarmuka objek (atau bahkan hanya membuat antarmuka yang memenuhi persyaratan metode dan tidak lebih).
  • Kemampuan untuk membuat adaptor atau berbagai pola serupa lainnya dengan lebih mudah dalam hal objek yang tidak dapat Anda campur tangani.
  • Menunda implementasi antarmuka, dan mengimplementasikannya nanti tanpa harus menyentuh implementasi yang sebenarnya, hanya mengimplementasikannya ketika Anda benar-benar ingin membuat implementor lain.
Jimmy Hoffa
sumber
Utilitas metode ekstensi di Linq sebagian besar berasal dari kemampuan mereka untuk mencangkokkan implementasi metode ke sebuah antarmuka, khususnya IEnumerabledan IQueryable. Meskipun Anda bisa memalsukan ini dengan staticmetode di kelas utilitas, itu akan menjadi canggung.
Robert Harvey
@RobertHarvey Ini tidak selalu akurat untuk mengklaim itu meletakkan metode pada antarmuka, perhatikan perbedaan antara metode aktual pada antarmuka dan metode ekstensi: Metode pada antarmuka akan diimplementasikan di dalam kelas yang mengimplementasikan antarmuka itu, dan oleh karena itu memiliki akses yang tersedia untuk banyak lebih dari metode ekstensi tidak. Sekali lagi ini adalah perubahan dalam perspektif, kode yang diimplementasikan di dalam kelas diberikan perspektif khusus dibandingkan dengan yang di luar.
Jimmy Hoffa