Alih-alih mendukung metode overload, Ruby menimpa metode yang ada. Adakah yang bisa menjelaskan mengapa bahasanya dirancang seperti ini?
146
Metode overloading dapat dicapai dengan mendeklarasikan dua metode dengan nama yang sama dan tanda tangan yang berbeda. Tanda tangan yang berbeda ini bisa berupa,
method(int a, int b) vs method(String a, String b)
method(a) vs method(a, b)
Kami tidak dapat mencapai metode overload menggunakan cara pertama karena tidak ada deklarasi tipe data di ruby ( bahasa pengetikan dinamis ). Jadi satu-satunya cara untuk mendefinisikan metode di atas adalahdef(a,b)
Dengan opsi kedua, sepertinya kita bisa mencapai metode overloading, tetapi kita tidak bisa. Katakanlah saya memiliki dua metode dengan jumlah argumen yang berbeda,
def method(a); end;
def method(a, b = true); end; # second argument has a default value
method(10)
# Now the method call can match the first one as well as the second one,
# so here is the problem.
Jadi ruby perlu mempertahankan satu metode dalam metode mencari rantai dengan nama yang unik.
"Kelebihan beban" adalah istilah yang bahkan tidak masuk akal di Ruby. Ini pada dasarnya adalah sinonim untuk "pengiriman berbasis argumen statis", tetapi Ruby tidak memiliki pengiriman statis sama sekali . Jadi, alasan mengapa Ruby tidak mendukung pengiriman statis berdasarkan argumen, adalah karena Ruby tidak mendukung pengiriman statis, titik. Itu tidak mendukung pengiriman statis dalam bentuk apa pun , baik berbasis argumen atau sebaliknya.
Sekarang, jika Anda tidak benar-benar secara spesifik bertanya tentang kelebihan muatan, tetapi mungkin tentang pengiriman berbasis argumen dinamis , maka jawabannya adalah: karena Matz tidak mengimplementasikannya. Karena tidak ada orang lain yang mau mengusulkannya. Karena tidak ada orang lain yang peduli untuk mengimplementasikannya.
Secara umum, pengiriman berbasis argumen dinamis dalam bahasa dengan argumen opsional dan daftar argumen panjang variabel, sangat sulit untuk diperbaiki, dan bahkan lebih sulit untuk membuatnya dimengerti. Bahkan dalam bahasa dengan pengiriman berbasis argumen statis dan tanpa argumen opsional (seperti Java, misalnya), kadang-kadang hampir tidak mungkin untuk mengatakan untuk manusia biasa, yang kelebihan beban akan dipilih.
Dalam C #, Anda benar-benar dapat menyandikan masalah 3-SAT ke resolusi kelebihan beban, yang berarti bahwa resolusi kelebihan beban di C # adalah NP-hard.
Sekarang coba dengan pengiriman dinamis , di mana Anda memiliki dimensi waktu tambahan untuk tetap di kepala Anda.
Ada bahasa yang secara dinamis mengirimkan berdasarkan semua argumen prosedur, sebagai lawan dari bahasa berorientasi objek, yang hanya mengirim pada "nol"
self
argumen yang tersembunyi . Lisp umum, misalnya, mengirimkan tipe dinamis dan bahkan nilai dinamis semua argumen. Clojure mengirimkan fungsi sewenang-wenang dari semua argumen (yang BTW sangat keren dan sangat kuat).Tapi saya tidak tahu bahasa OO dengan pengiriman berbasis argumen yang dinamis. Martin Odersky mengatakan bahwa ia mungkin mempertimbangkan untuk menambahkan pengiriman berbasis argumen ke Scala, tetapi hanya jika ia dapat menghapus kelebihan muatan pada saat yang sama dan kompatibel dengan keduanya dengan kode Scala yang ada yang menggunakan kelebihan muatan dan kompatibel dengan Java (ia terutama menyebut Swing dan AWT yang memainkan beberapa trik yang sangat kompleks dengan melakukan hampir setiap kasus sudut gelap yang buruk dari aturan overload yang agak rumit dari Java) Saya sendiri memiliki beberapa ide tentang menambahkan pengiriman berbasis argumen ke Ruby, tetapi saya tidak pernah tahu bagaimana melakukannya dengan cara yang kompatibel dengan mundur.
sumber
def method(a, b = true)
tidak akan bekerja, oleh karena itu metode overloading tidak mungkin." Ini bukan; itu hanya sulit. Namun, saya menemukan jawaban ini sangat informatif.Saya kira Anda sedang mencari kemampuan untuk melakukan ini:
Ruby mendukung ini dengan cara yang berbeda:
Pola umum juga untuk meneruskan opsi sebagai hash:
Semoga itu bisa membantu
sumber
Metode overloading masuk akal dalam bahasa dengan pengetikan statis, di mana Anda dapat membedakan berbagai jenis argumen
serta antara jumlah argumen yang berbeda
Perbedaan pertama tidak ada di ruby. Ruby menggunakan pengetikan dinamis atau "pengetikan bebek". Perbedaan kedua dapat ditangani oleh argumen default atau dengan bekerja dengan argumen:
sumber
Ini tidak menjawab pertanyaan mengapa ruby tidak memiliki kelebihan metode, tetapi perpustakaan pihak ketiga dapat menyediakannya.
The contracts.ruby perpustakaan memungkinkan overloading. Contoh diadaptasi dari tutorial:
Perhatikan bahwa ini sebenarnya lebih kuat daripada kelebihan beban Java, karena Anda dapat menentukan nilai yang cocok (misalnya
1
), bukan hanya tipe.Anda akan melihat penurunan kinerja menggunakan ini; Anda harus menjalankan tolok ukur untuk memutuskan seberapa banyak Anda bisa mentolerir.
sumber
Saya sering melakukan struktur berikut:
Ini memungkinkan pengguna objek untuk menggunakan method_name: metode yang bersih dan jelas. Tetapi jika ia ingin mengoptimalkan eksekusi, ia dapat langsung memanggil metode yang benar.
Juga, itu membuat tes Anda lebih jelas dan lebih baik.
sumber
sudah ada jawaban bagus mengapa dari sisi pertanyaan. Namun, jika ada yang mencari solusi lain, periksa permata fungsional-ruby yang terinspirasi oleh fitur pencocokan pola Elixir .
sumber