Meskipun mungkin ada kasus yang valid di mana metode overloading bisa menjadi ambigu, mengapa kompiler melarang kode yang tidak ambigu pada waktu kompilasi atau pada saat run time?
Contoh:
// This fails:
def foo(a: String)(b: Int = 42) = a + b
def foo(a: Int) (b: Int = 42) = a + b
// This fails, too. Even if there is no position in the argument list,
// where the types are the same.
def foo(a: Int) (b: Int = 42) = a + b
def foo(a: String)(b: String = "Foo") = a + b
// This is OK:
def foo(a: String)(b: Int) = a + b
def foo(a: Int) (b: Int = 42) = a + b
// Even this is OK.
def foo(a: Int)(b: Int) = a + b
def foo(a: Int)(b: String = "Foo") = a + b
val bar = foo(42)_ // This complains obviously ...
Adakah alasan mengapa pembatasan ini tidak bisa dilonggarkan sedikit?
Terutama ketika mengonversi kode Java yang kelebihan beban ke argumen default Scala adalah sangat penting dan tidak baik untuk mengetahuinya setelah mengganti banyak metode Java dengan satu metode Scala yang spek / kompiler memberlakukan pembatasan sewenang-wenang.
object Test { def a[A](b: Int, c: Int, d: Int = 7): Unit = {}; def a[A](a:String, b: String = ""): Unit = {}; a(2,3,4); a("a");}
Jawaban:
Saya ingin mengutip Lukas Rytz (dari sini ):
Solusi untuk versi Scala di masa depan bisa dengan memasukkan nama tipe dari argumen non-default (yang di awal metode, yang mendambiguasi versi kelebihan beban) ke dalam skema penamaan, misalnya dalam kasus ini:
itu akan menjadi seperti:
Seseorang mau menulis proposal SIP ?
sumber
A with B
, misalnya?Akan sangat sulit untuk mendapatkan spesifikasi yang dapat dibaca dan tepat untuk interaksi resolusi kelebihan beban dengan argumen default. Tentu saja, untuk banyak kasus individual, seperti yang disajikan di sini, mudah untuk mengatakan apa yang harus terjadi. Tetapi itu tidak cukup. Kami membutuhkan spesifikasi yang memutuskan semua kasus sudut yang memungkinkan. Resolusi overloading sudah sangat sulit ditentukan. Menambahkan argumen default dalam campuran akan membuatnya lebih sulit lagi. Itu sebabnya kami memilih untuk memisahkan keduanya.
sumber
Saya tidak bisa menjawab pertanyaan Anda, tetapi ini solusinya:
Jika Anda memiliki dua daftar arg yang sangat panjang yang berbeda hanya dalam satu arg, itu mungkin sepadan dengan masalahnya ...
sumber
Either
dan bukan hanya untukfoo
- dengan cara ini, kapan pun suatuEither[A, B]
nilai diminta, keduanyaA
danB
diterima. Seseorang seharusnya mendefinisikan tipe yang hanya diterima oleh fungsi yang memiliki argumen default (seperti difoo
sini), jika Anda ingin pergi ke arah ini; tentu saja, menjadi semakin tidak jelas apakah ini solusi yang nyaman.Apa yang berhasil bagi saya adalah mendefinisikan kembali (gaya Java) metode overloading.
Ini memastikan kompiler resolusi apa yang Anda inginkan sesuai dengan parameter yang ada.
sumber
Berikut adalah generalisasi jawaban @Landei:
Apa yang benar-benar Anda inginkan:
Workarround
sumber
Salah satu skenario yang mungkin adalah
Kompiler akan bingung tentang yang harus dipanggil. Dalam pencegahan kemungkinan bahaya lain, kompiler akan memungkinkan paling banyak satu metode kelebihan beban memiliki argumen default.
Hanya tebakan saya :-)
sumber
Pemahaman saya adalah bahwa mungkin ada tabrakan nama di kelas yang dikompilasi dengan nilai argumen default. Saya telah melihat sesuatu di sepanjang baris ini yang disebutkan dalam beberapa utas.
Spec argumen bernama di sini: http://www.scala-lang.org/sites/default/files/sids/rytz/Mon,%202009-11-09,%2017:29/named-args.pdf
Ini menyatakan:
Jadi, untuk sementara waktu, itu tidak akan berhasil.
Anda dapat melakukan sesuatu seperti apa yang mungkin Anda lakukan di Jawa, misalnya:
sumber