Apakah metode kelebihan jenis polimorfisme? Bagi saya sepertinya hanya diferensiasi metode dengan nama dan parameter yang sama. Jadi stuff(Thing t)
dan stuff(Thing t, int n)
metode yang sama sekali berbeda sejauh menyangkut kompiler dan runtime.
Ini menciptakan ilusi, di sisi penelepon, bahwa itu adalah metode yang sama yang bertindak berbeda pada berbagai jenis objek - polimorfisme. Tapi itu hanya ilusi, karena sebenarnya stuff(Thing t)
dan stuff(Thing t, int n)
metode yang sama sekali berbeda.
Apakah metode kelebihan muatan lebih dari sekadar gula sintaksis? Apakah saya melewatkan sesuatu?
Definisi umum untuk gula sintaksis, adalah bahwa gula itu murni lokal . Berarti mengubah sepotong kode ke 'manisnya' yang setara, atau sebaliknya, melibatkan perubahan lokal yang tidak mempengaruhi struktur keseluruhan program. Dan saya pikir metode overloading cocok dengan kriteria ini. Mari kita lihat contoh untuk menunjukkan:
Pertimbangkan kelas:
class Reader {
public String read(Book b){
// .. translate the book to text
}
public String read(File b){
// .. translate the file to text
}
}
Sekarang pertimbangkan kelas lain yang menggunakan kelas ini:
/* might not be the best example */
class FileProcessor {
Reader reader = new Reader();
public void process(File file){
String text = reader.read(file);
// .. do stuff with the text
}
}
Baik. Sekarang mari kita lihat apa yang perlu diubah jika kita mengganti metode overloading dengan metode biasa:
The read
metode dalam Reader
perubahan readBook(Book)
dan readFile(file)
. Hanya masalah mengubah nama mereka.
Kode panggilan FileProcessor
sedikit reader.read(file)
berubah : berubah menjadi reader.readFile(file)
.
Dan itu saja.
Seperti yang Anda lihat, perbedaan antara menggunakan metode overloading dan tidak menggunakannya, adalah murni lokal . Dan itulah mengapa saya pikir itu memenuhi syarat sebagai gula sintaksis murni.
Saya ingin mendengar keberatan Anda jika ada, mungkin saya kehilangan sesuatu.
sumber
Jawaban:
Untuk menjawab ini, pertama Anda perlu definisi untuk "gula sintaksis." Saya akan menggunakan Wikipedia :
Jadi, di bawah definisi ini, fitur-fitur seperti Java varargs atau Scala untuk pemahaman adalah gula sintaksis: mereka menerjemahkan ke dalam fitur bahasa yang mendasarinya (array dalam kasus pertama, panggilan untuk memetakan / flatmap / filter dalam yang kedua), dan menghapusnya akan tidak mengubah hal-hal yang dapat Anda lakukan dengan bahasa tersebut.
Metode overloading, bagaimanapun, bukanlah gula sintaksis di bawah definisi ini, karena menghapusnya secara mendasar akan mengubah bahasa (Anda tidak akan lagi dapat mengirim ke perilaku yang berbeda berdasarkan argumen).
Benar, Anda dapat mensimulasikan overloading metode selama Anda memiliki beberapa cara untuk mengakses argumen metode, dan dapat menggunakan konstruksi "jika" berdasarkan argumen yang Anda berikan. Tetapi jika Anda menganggap itu gula sintaksis, Anda harus mempertimbangkan apa pun di atas mesin Turing untuk menjadi gula sintaksis.
sumber
sum(numbersArray)
dansum(numbersList)
bukannyasumArray(numbersArray)
dansumList(numbersList)
. Saya setuju dengan Doval, sepertinya gula sintaksis belaka.instanceof
, kelas, warisan, antarmuka, obat generik, refleksi atau penspesifikasi akses menggunakanif
,while
dan operator boolean, dengan semantik yang sama persis . Tidak ada kasus sudut. Perhatikan bahwa saya tidak menantang Anda untuk menghitung hal yang sama seperti penggunaan spesifik konstruksi tersebut. Saya sudah tahu Anda bisa menghitung apa saja menggunakan logika boolean dan branching / looping. Saya meminta Anda untuk menerapkan salinan semantik yang sempurna dari fitur-fitur bahasa tersebut, termasuk jaminan statis yang disediakannya (kompilasi pemeriksaan waktu masih harus dilakukan pada waktu kompilasi.)Istilah gula sintaksis biasanya merujuk pada kasus-kasus di mana fitur didefinisikan oleh substitusi. Bahasa tidak mendefinisikan apa yang dilakukan fitur, melainkan mendefinisikan bahwa itu persis setara dengan sesuatu yang lain. Jadi misalnya, untuk setiap loop
Menjadi:
Atau ambil fungsi dengan argumen variabel:
Yang menjadi:
Jadi ada subtitusi sintaksis sepele untuk mengimplementasikan fitur dalam hal fitur lainnya.
Mari kita lihat metode overloading.
Ini dapat ditulis ulang sebagai:
Tapi itu tidak setara dengan itu. Dalam model Jawa, ini adalah sesuatu yang berbeda.
foo(int a)
tidak mengimplementasikanfoo_int
fungsi yang akan dibuat. Java tidak menerapkan metode overloading dengan memberi fungsi ambigu nama lucu. Untuk menghitung sebagai gula sintaksis, java harus berpura-pura bahwa Anda benar-benar menulisfoo_int
danfoo_double
berfungsi tetapi tidak.sumber
But, the transformation isn't trivial. At the least, you have to determine the types of the parameters.
sangat samar karena jenisnya tidak perlu ditentukan ; mereka dikenal pada waktu kompilasi.foo(int)
/foo(double)
danfoo_int
/foo_double
? Saya tidak benar-benar mengenal Java dengan sangat baik tetapi saya akan membayangkan bahwa penggantian nama seperti itu benar-benar terjadi di JVM (well - mungkin menggunakanfoo(args)
lebih dari itufoo_args
- itu setidaknya dalam C ++ dengan simbol mangling (ok - simbol mangling secara teknis merupakan detail implementasi dan bukan bagian bahasa)for
loop yang disempurnakan tidak lebih ekspresif daripada Java tanpa itu. (Ini lebih bagus, lebih ringkas, lebih mudah dibaca, dan lebih baik, saya berpendapat, tapi tidak lebih ekspresif.) Namun, saya tidak yakin dengan kasus kelebihan beban. Saya mungkin harus membaca ulang koran untuk memastikan. Menurut saya itu adalah gula sintaksis, tetapi saya tidak yakin.Mengingat nama itu berfungsi, bukankah itu tidak lebih dari gula sintaksis?
Ini memungkinkan penelepon untuk membayangkan dia memanggil fungsi yang sama, ketika dia tidak. Tapi ia bisa mengetahui yang sebenarnya nama-nama dari semua fungsi nya. Hanya jika dimungkinkan untuk mencapai polimorfisme yang tertunda dengan mengirimkan variabel yang tidak diketik ke dalam fungsi yang diketik dan jenisnya ditetapkan sehingga panggilan bisa pergi ke versi yang tepat sesuai dengan nama maka ini akan menjadi fitur bahasa yang sebenarnya.
Sayangnya, saya belum pernah melihat bahasa melakukan ini. Ketika ada ambiguitas, kompiler ini tidak menyelesaikannya, mereka mendesak penulis untuk menyelesaikannya.
sumber
dynamic
kemudian resolusi kelebihan terjadi pada saat runtime, bukan pada waktu kompilasi . Itulah multi-pengiriman, dan tidak dapat direplikasi dengan mengganti nama fungsi.Tergantung pada bahasanya, itu adalah gula sintaksis atau tidak.
Di C ++ misalnya, Anda dapat melakukan hal-hal menggunakan kelebihan beban dan templat yang tidak akan mungkin terjadi tanpa komplikasi (tulis secara manual semua instantiasi templat atau tambahkan banyak parameter templat).
Perhatikan bahwa pengiriman dinamis adalah bentuk kelebihan muatan, diselesaikan secara dinamis pada beberapa parameter (untuk beberapa bahasa hanya yang khusus, ini , tetapi tidak semua bahasa sangat terbatas), dan saya tidak akan menyebut bentuk kelebihan sintaksis gula.
sumber
Untuk bahasa kontemporer, itu hanya gula sintaksis; dalam cara bahasa-agnostik sepenuhnya, itu lebih dari itu.
Sebelumnya jawaban ini hanya menyatakan bahwa itu lebih dari sekadar gula sintaksis, tetapi jika Anda akan melihat di komentar, Falco mengemukakan masalah bahwa ada satu bagian teka-teki yang sepertinya tidak ada dalam bahasa kontemporer; mereka tidak mencampur metode overloading dengan penentuan dinamis fungsi mana yang dipanggil dalam langkah yang sama. Ini akan diklarifikasi nanti.
Inilah mengapa itu harus lebih.
Pertimbangkan bahasa yang mendukung variabel overloading dan variabel yang tidak diketik. Anda dapat memiliki prototipe metode berikut:
Dalam beberapa bahasa, Anda mungkin akan pasrah mengetahui pada waktu kompilasi mana yang akan dipanggil oleh baris kode tertentu. Tetapi dalam beberapa bahasa, tidak semua variabel diketik (atau mereka semua secara implisit diketik sebagai
Object
atau apa pun), jadi bayangkan membangun kamus yang kuncinya memetakan nilai-nilai dari jenis yang berbeda:Nah, bagaimana jika Anda ingin menerapkan
someFunction
ke salah satu nomor kamar itu? Anda menyebutnya:Apakah
someFunction(int)
disebut, atausomeFunction(string)
disebut? Di sini Anda melihat satu contoh di mana ini bukan metode yang sepenuhnya ortogonal, terutama dalam bahasa tingkat tinggi. Bahasa harus mencari tahu - selama runtime - mana yang harus dipanggil, jadi masih harus menganggap ini sebagai metode yang setidaknya sama.Mengapa tidak menggunakan templat saja? Mengapa tidak menggunakan argumen yang tidak diketik?
Fleksibilitas dan kontrol yang lebih halus. Terkadang menggunakan template / argumen yang tidak diketik merupakan pendekatan yang lebih baik, tetapi terkadang tidak.
Anda harus memikirkan kasus-kasus di mana, misalnya, Anda mungkin memiliki dua tanda tangan metode yang masing-masing mengambil argumen
int
a dan astring
, tetapi urutannya berbeda di setiap tanda tangan. Anda mungkin memiliki alasan yang kuat untuk melakukan ini, karena implementasi setiap tanda tangan mungkin melakukan hal yang sama, tetapi dengan sedikit perbedaan; penebangan bisa berbeda, misalnya. Atau bahkan jika mereka melakukan hal yang persis sama, Anda mungkin dapat secara otomatis mengumpulkan informasi tertentu hanya dari urutan argumen yang ditentukan. Secara teknis Anda hanya bisa menggunakan pernyataan pseudo-switch untuk menentukan jenis setiap argumen yang diteruskan, tetapi itu menjadi berantakan.Jadi apakah ini contoh praktik pemrograman yang buruk selanjutnya?
Ya, pada umumnya. Dalam contoh khusus ini, ini dapat mencegah seseorang mencoba menerapkan ini pada tipe primitif tertentu dan mendapatkan kembali perilaku yang tidak terduga (yang bisa menjadi hal yang baik); tapi anggap saja saya menyingkat kode di atas, dan bahwa Anda, pada kenyataannya, memiliki kelebihan untuk semua jenis primitif, serta untuk
Object
s. Maka bit kode berikut ini benar-benar lebih tepat:Tetapi bagaimana jika Anda hanya perlu menggunakan ini untuk
int
s danstring
s, dan bagaimana jika Anda ingin mengembalikannya berdasarkan pada kondisi yang lebih sederhana atau lebih rumit? Maka Anda memiliki alasan yang bagus untuk menggunakan kelebihan beban:Tapi hei, mengapa tidak memberikan fungsi-fungsi itu dua nama yang berbeda? Anda masih memiliki jumlah kendali yang sama, bukan?
Karena, seperti yang dinyatakan sebelumnya, beberapa hotel menggunakan angka, beberapa menggunakan huruf, dan beberapa menggunakan campuran angka dan huruf:
Ini masih bukan kode persis sama persis yang akan saya gunakan dalam kehidupan nyata, tetapi harus menggambarkan hal yang saya buat dengan baik.
Tapi ... Inilah sebabnya mengapa itu tidak lebih dari gula sintaksis dalam bahasa kontemporer.
Falco mengangkat pokok bahasan di komentar bahwa bahasa saat ini pada dasarnya tidak mencampur metode overloading dan pemilihan fungsi dinamis dalam langkah yang sama. Cara saya sebelumnya memahami bahasa tertentu untuk bekerja adalah bahwa Anda dapat membebani
appearsToBeFirstFloor
dalam contoh di atas, dan kemudian bahasa akan menentukan pada saat runtime versi fungsi yang akan dipanggil, tergantung pada nilai runtime dari variabel yang tidak diketik. Kebingungan ini sebagian berasal dari bekerja dengan ECMA-macam bahasa, seperti ActionScript 3.0, di mana Anda dapat dengan mudah mengacak fungsi mana dipanggil pada baris kode tertentu saat runtime.Seperti yang Anda ketahui, ActionScript 3 tidak mendukung kelebihan metode. Adapun VB.NET, Anda dapat mendeklarasikan dan mengatur variabel tanpa menetapkan jenis secara eksplisit, tetapi ketika Anda mencoba untuk mengirimkan variabel-variabel ini sebagai argumen untuk metode kelebihan beban, masih tidak ingin membaca nilai runtime untuk menentukan metode yang akan dipanggil; alih-alih ingin menemukan metode dengan argumen tipe
Object
atau tanpa tipe atau yang lain seperti itu. Jadi contohint
vs. distring
atas tidak akan berfungsi dalam bahasa itu juga. C ++ memiliki masalah serupa, seperti ketika Anda menggunakan sesuatu seperti void pointer atau mekanisme lain seperti itu, C ++ masih mengharuskan Anda untuk secara manual mengaburkan tipe pada waktu kompilasi.Jadi seperti tajuk pertama mengatakan ...
Untuk bahasa kontemporer, itu hanya gula sintaksis; dalam cara bahasa-agnostik sepenuhnya, itu lebih dari itu. Membuat metode overloading lebih bermanfaat dan relevan, seperti dalam contoh di atas, sebenarnya bisa menjadi fitur yang baik untuk ditambahkan ke bahasa yang ada (seperti yang secara luas diminta untuk AS3), atau itu juga bisa berfungsi sebagai salah satu di antara banyak pilar fundamental berbeda untuk penciptaan bahasa berorientasi prosedural / objek baru.
sumber
this[chooseFunctionNameAtRandom]();
JikachooseFunctionNameAtRandom()
pengembalian baik"punch"
,"kick"
atau"dodge"
, maka Anda dapat thusly menerapkan sangat simple random elemen dalam, misalnya, AI musuh dalam game Flash.Itu benar-benar tergantung pada definisi Anda tentang "gula sintaksis". Saya akan mencoba membahas beberapa definisi yang muncul di benak saya:
Suatu fitur adalah gula sintaksis ketika suatu program yang menggunakannya selalu dapat diterjemahkan dalam bahasa lain yang tidak menggunakan fitur tersebut.
Di sini kita mengasumsikan bahwa ada seperangkat fitur primitif yang tidak dapat diterjemahkan: dengan kata lain tidak ada loop dari jenis "Anda dapat mengganti fitur X menggunakan fitur Y" dan "Anda dapat mengganti fitur Y dengan fitur X". Jika salah satu dari keduanya benar dari salah satu fitur yang lain dapat dinyatakan dalam hal fitur yang bukan yang pertama atau itu adalah fitur primitif.
Sama seperti definisi 1 tetapi dengan persyaratan tambahan bahwa program yang diterjemahkan adalah jenis-aman sebagai yang pertama, yaitu dengan keinginan Anda tidak kehilangan segala jenis informasi.
Definisi OP: fitur adalah gula sintaksis jika terjemahannya tidak mengubah struktur program tetapi hanya membutuhkan "perubahan lokal".
Mari kita ambil Haskell sebagai contoh untuk kelebihan muatan. Haskell menyediakan overloading yang ditentukan pengguna melalui kelas tipe. Sebagai contoh,
+
dan*
operasi didefinisikan dalamNum
kelas tipe dan tipe apa pun yang memiliki turunan (lengkap) dari kelas tersebut dapat digunakan+
. Sebagai contoh:Satu hal yang terkenal tentang kelas tipe Haskell adalah Anda dapat menyingkirkannya . Yaitu Anda dapat menerjemahkan program apa pun yang menggunakan kelas tipe di program yang setara yang tidak menggunakannya.
Terjemahannya cukup sederhana:
Diberi definisi kelas:
Anda bisa menerjemahkannya ke tipe data aljabar:
Di sini
X_P_i
danX_op_i
merupakan pemilih . Yaitu diberi nilai tipe yangX a
menerapkanX_P_1
nilai akan mengembalikan nilai yang disimpan di bidang itu, sehingga mereka berfungsi dengan tipeX a -> P_i a
(atauX a -> t_i
).Untuk anologi yang sangat kasar, Anda bisa memikirkan nilai untuk tipe
X a
sebagaistruct
s dan kemudian jikax
adalah tipeX a
ekspresi:dapat dilihat sebagai:
(Sangat mudah untuk menggunakan hanya bidang posisi daripada bidang bernama, tetapi bidang bernama lebih mudah ditangani dalam contoh dan menghindari beberapa kode pelat-ketel).
Diberikan contoh deklarasi:
Anda bisa menerjemahkannya ke dalam fungsi yang memberikan kamus untuk
C_1 a_1, ..., C_n a_n
kelas mengembalikan nilai kamus (yaitu nilai jenisX a
) untuk jenisT a_1 ... a_n
.Dengan kata lain instance di atas dapat diterjemahkan ke fungsi seperti:
(Perhatikan itu
n
mungkin0
).Dan sebenarnya kita dapat mendefinisikannya sebagai:
di mana
op_1 = ...
untukop_m = ...
adalah definisi yang ditemukan diinstance
deklarasi danget_P_i_T
adalah fungsi yang didefinisikan olehP_i
contoh dariT
jenis (ini harus ada karenaP_i
s adalah superclasses dariX
).Diberi panggilan ke fungsi kelebihan beban:
Kami dapat secara eksplisit melewati kamus relatif terhadap batasan kelas dan mendapatkan panggilan yang setara:
Perhatikan bagaimana batasan kelas hanya menjadi argumen baru. Program
+
yang diterjemahkan adalah pemilih seperti yang dijelaskan sebelumnya. Dengan kata lainadd
fungsi yang diterjemahkan , diberikan kamus untuk jenis argumennya pertama-tama akan "membongkar" fungsi aktual untuk menghitung hasil menggunakan(+) dictNum
dan kemudian akan menerapkan fungsi ini ke argumen.Ini hanya sketsa yang sangat cepat tentang semuanya. Jika Anda tertarik, Anda harus membaca artikel Simon Peyton Jones et al.
Saya percaya pendekatan serupa dapat digunakan untuk kelebihan dalam bahasa lain juga.
Namun ini menunjukkan bahwa, jika definisi Anda tentang gula sintaksis adalah (1), maka kelebihannya adalah gula sintaksis . Karena Anda dapat menyingkirkannya.
Namun program yang diterjemahkan kehilangan beberapa informasi tentang program yang asli. Sebagai contoh itu tidak menegaskan bahwa instance untuk kelas induk ada. (Meskipun operasi untuk mengekstrak kamus induk harus masih dari jenis itu, Anda bisa
undefined
memasukkan atau nilai-nilai polimorfik lainnya sehingga Anda dapat membangun nilai untukX y
tanpa membangun nilai-nilai untukP_i y
, sehingga terjemahan tidak kehilangan semua jenis keamanannya). Karenanya itu bukan gula sintaksis menurut (2)Adapun (3). Saya tidak tahu apakah jawabannya harus ya atau tidak.
Saya akan mengatakan tidak karena, misalnya, deklarasi instance menjadi definisi fungsi. Fungsi yang kelebihan beban mendapatkan parameter baru (yang berarti ia mengubah definisi dan semua panggilan).
Saya akan mengatakan ya karena kedua program masih memetakan satu-ke-satu, sehingga "struktur" sebenarnya tidak banyak berubah.
Ini mengatakan, saya akan mengatakan bahwa keuntungan pragmatis yang diperkenalkan oleh kelebihan beban sangat besar sehingga menggunakan istilah "merendahkan" seperti "gula sintaksis" tampaknya tidak benar.
Anda dapat menerjemahkan semua sintaksis Haskell ke bahasa Core yang sangat sederhana (yang sebenarnya dilakukan saat kompilasi), sehingga sebagian besar sintaksis Haskell dapat dilihat sebagai "gula sintaksis" untuk sesuatu yang hanya lambda-kalkulus plus sedikit konstruksi baru. Namun kami dapat menyetujui bahwa program-program Haskell lebih mudah untuk ditangani dan sangat ringkas, sedangkan program-program yang diterjemahkan lebih sulit untuk dibaca atau dipikirkan.
sumber
Jika pengiriman diselesaikan pada waktu kompilasi, hanya bergantung pada jenis statis dari argumen argumen, maka Anda tentu dapat berpendapat bahwa itu "gula sintaksis" menggantikan dua metode yang berbeda dengan nama yang berbeda, asalkan programmer "tahu" tipe statis dan hanya bisa menggunakan nama metode yang tepat di tempat nama yang kelebihan beban. Ini juga merupakan bentuk polimorfisme statis, tetapi dalam bentuk terbatas itu biasanya tidak terlalu kuat.
Tentu saja itu akan menjadi gangguan untuk harus mengubah nama metode yang Anda panggil setiap kali Anda mengubah jenis variabel, tetapi misalnya dalam bahasa C itu dianggap gangguan yang dapat dikelola, sehingga C tidak memiliki fungsi yang berlebihan (walaupun sekarang memiliki macro generik).
Dalam templat C ++, dan dalam bahasa apa pun yang melakukan deduksi tipe statis non-sepele, Anda tidak dapat benar-benar berdebat bahwa ini adalah "gula sintaksis" kecuali Anda juga berpendapat bahwa deduksi tipe statis adalah "gula sintaksis". Ini akan menjadi gangguan untuk tidak memiliki template, dan dalam konteks C ++ itu akan menjadi "gangguan yang tidak dapat dikelola", karena mereka sangat idiomatis dengan bahasa dan perpustakaan standarnya. Jadi dalam C ++ ini lebih dari sekadar pembantu yang bagus, sangat penting untuk gaya bahasa, dan jadi saya pikir Anda harus menyebutnya lebih dari "gula sintaksis".
Di Jawa Anda bisa mempertimbangkan lebih dari sekedar kenyamanan mempertimbangkan misalnya berapa banyak overloads ada dari
PrintStream.print
danPrintStream.println
. Tetapi kemudian, ada banyakDataInputStream.readX
metode karena Java tidak kelebihan pada tipe kembali, jadi dalam beberapa hal itu hanya untuk kenyamanan. Itu semua untuk tipe primitif.Saya tidak ingat apa yang terjadi di Jawa jika saya memiliki kelas
A
danB
memperluasO
, saya membebani metodefoo(O)
,foo(A)
danfoo(B)
, kemudian dalam generik dengan<T extends O>
saya sebut difoo(t)
manat
adalah contohT
. Dalam kasus di manaT
adalahA
saya mendapatkan pengiriman berdasarkan kelebihan atau itu seolah-olah aku meneleponfoo(O)
?Jika yang pertama, maka kelebihan metode Java lebih baik daripada gula dengan cara yang sama seperti kelebihan C ++. Menggunakan definisi Anda, saya kira di Jawa saya bisa secara lokal menulis serangkaian pemeriksaan tipe (yang akan rapuh, karena kelebihan baru
foo
akan memerlukan pemeriksaan tambahan). Selain menerima kerapuhan itu saya tidak bisa membuat perubahan lokal di situs panggilan untuk memperbaikinya, sebaliknya saya harus menyerah menulis kode generik. Saya berpendapat bahwa mencegah kode kembung mungkin gula sintaksis, tetapi mencegah kode rapuh lebih dari itu. Karena itu, polimorfisme statis pada umumnya lebih dari sekadar gula sintaksis. Situasi dalam bahasa tertentu mungkin berbeda, tergantung seberapa jauh bahasa tersebut memungkinkan Anda untuk mendapatkan "tidak tahu" jenis statis.sumber
T:Animal
ini adalah jenisSiameseCat
dan overloads yang adaCat Foo(Animal)
,SiameseCat Foo(Cat)
danAnimal Foo(SiameseCat)
yang berlebihan harus dipilih jikaT
iniSiameseCat
?long foo=Math.round(bar*1.0001)*5
diubah menjadilong foo=Math.round(bar)*5
. Bagaimana hal itu mempengaruhi semantik jikabar
sama dengan, misalnya, 123456789L?long
kedouble
.double
?Sepertinya "gula sintaksis" terdengar menghina, seperti tidak berguna atau sembrono. Itu sebabnya pertanyaan itu memicu banyak jawaban negatif.
Tapi Anda benar, metode overloading tidak menambahkan fitur apa pun ke bahasa kecuali kemungkinan untuk menggunakan nama yang sama untuk metode yang berbeda. Anda dapat membuat tipe parameter eksplisit, program akan tetap bekerja sama.
Hal yang sama berlaku untuk nama paket. String hanyalah gula sintaksis untuk java.lang.String.
Bahkan, metode seperti
di kelas MyClass harus disebut sesuatu seperti "my_package_MyClass_fun_int_java_lang_String". Ini akan mengidentifikasi metode secara unik. (JVM melakukan sesuatu seperti itu secara internal). Tetapi Anda tidak ingin menulis itu. Itulah sebabnya kompiler akan membiarkan Anda menulis kesenangan (1, "satu") dan mengidentifikasi metode mana itu.
Namun ada satu hal yang dapat Anda lakukan dengan overloading: Jika Anda membebani metode dengan jumlah argumen yang sama, kompiler akan mencari tahu versi mana yang paling cocok dengan argumen yang diberikan oleh argumen yang cocok, tidak hanya dengan jenis yang sama, tetapi juga di mana argumen yang diberikan adalah subkelas dari argumen yang dideklarasikan.
Jika Anda memiliki dua prosedur kelebihan beban
Anda tidak perlu tahu bahwa ada versi spesifik dari prosedur untuk Tanggal. addParameter ("hello", "world) akan memanggil versi pertama, addParameter (" now ", Date baru ()) akan memanggil versi kedua.
Tentu saja, Anda harus menghindari kelebihan metode dengan metode lain yang melakukan hal yang sama sekali berbeda.
sumber
Menariknya, jawaban untuk pertanyaan ini akan tergantung pada bahasanya.
Secara khusus, ada interaksi antara overloading dan pemrograman generik (*), dan tergantung pada bagaimana pemrograman generik diimplementasikan mungkin hanya gula sintaksis (Karat) atau benar-benar diperlukan (C ++).
Yaitu, ketika pemrograman generik diimplementasikan dengan antarmuka eksplisit (dalam Rust atau Haskell, mereka akan menjadi kelas tipe), maka overloading hanyalah gula sintaksis; atau bahkan mungkin bukan bagian dari bahasa.
Di sisi lain, ketika pemrograman generik diimplementasikan dengan mengetik bebek (baik itu dinamis atau statis) maka nama metode ini merupakan kontrak yang penting, dan oleh karena itu kelebihan beban adalah wajib bagi sistem untuk bekerja.
(*) Digunakan dalam arti menulis metode sekali, untuk mengoperasikan berbagai jenis dengan cara yang seragam.
sumber
Dalam beberapa bahasa tidak diragukan lagi hanya gula sintaksis. Namun, apa itu gula tergantung pada sudut pandang Anda. Saya akan meninggalkan diskusi ini untuk nanti dalam jawaban ini.
Untuk saat ini saya hanya ingin mencatat bahwa dalam beberapa bahasa itu tentu saja bukan gula sintaksis. Setidaknya tidak tanpa mengharuskan Anda untuk menggunakan logika / algoritma yang sama sekali berbeda untuk mengimplementasikan hal yang sama. Ini seperti mengklaim rekursi adalah gula sintaksis (yang karena Anda dapat menulis semua algoritma rekursif dengan loop dan tumpukan).
Salah satu contoh penggunaan yang sangat sulit untuk diganti berasal dari bahasa yang ironisnya tidak menyebut fitur ini "function overloading". Sebaliknya itu disebut "pencocokan pola" (yang dapat dilihat sebagai superset dari overloading karena kita dapat membebani bukan hanya tipe tetapi juga nilai).
Inilah implementasi klasik naif dari fungsi Fibonacci di Haskell:
Tiga fungsi tersebut bisa diganti dengan if / else seperti yang biasa dilakukan dalam bahasa lain. Tapi itu pada dasarnya membuat definisi yang sangat sederhana:
jauh lebih berantakan dan tidak secara langsung mengekspresikan gagasan matematika dari deret Fibonacci.
Jadi kadang-kadang bisa berupa sintaksis gula jika hanya digunakan untuk memungkinkan Anda memanggil fungsi dengan argumen yang berbeda. Tetapi terkadang itu jauh lebih mendasar dari itu.
Sekarang untuk kebijaksanaan apa kelebihan operator mungkin menjadi gula. Anda telah mengidentifikasi satu use case - dapat digunakan untuk mengimplementasikan fungsi serupa yang menggunakan argumen berbeda. Begitu:
dapat juga diimplementasikan sebagai:
atau bahkan:
Tetapi overloading operator juga bisa menjadi gula untuk mengimplementasikan argumen opsional (beberapa bahasa memiliki overloading operator tetapi bukan argumen opsional):
dapat digunakan untuk mengimplementasikan:
Dalam bahasa seperti itu (google "Bahasa Ferit") menghapus overloading operator secara drastis menghapus satu fitur - argumen opsional. Diberikan dalam bahasa dengan kedua fitur (c ++) menghapus satu atau yang lain tidak akan memiliki efek bersih karena keduanya dapat digunakan untuk mengimplementasikan argumen opsional.
sumber
data PaymentInfo = CashOnDelivery | Adress String | UserInvoice CustomerInfo
Anda dapat mencocokkan pola pada konstruktor tipe.getPayment :: PaymentInfo -> a
getPayment CashOnDelivery = error "Should have been paid already"
getPayment (Adress addr) = -- code to notify administration to send a bill
getPayment (UserInvoice cust) = --whatever. I took the data type from a Haskell tutorial and have no idea what an invoice is
. Saya harap komentar ini bisa dimengerti.Saya pikir ini adalah gula sintaksis sederhana dalam sebagian besar bahasa (setidaknya yang saya tahu ...) karena mereka semua memerlukan Function-call yang tidak diragukan pada saat kompilasi. Dan kompiler hanya mengganti panggilan fungsi dengan pointer eksplisit ke tanda tangan implementasi yang tepat.
Contoh di Jawa:
Jadi pada akhirnya itu bisa sepenuhnya digantikan oleh kompiler-makro sederhana dengan pencarian dan ganti, mengganti fungsi mangle yang kelebihan beban dengan mangle_String dan mangle_int - karena argumen-daftar adalah bagian dari pengenal fungsi akhirnya ini praktis apa yang terjadi -> dan oleh karena itu hanya gula sintaksis.
Sekarang jika ada bahasa, di mana fungsi benar-benar ditentukan saat runtime, seperti dengan Metode yang ditimpa dalam objek, ini akan berbeda. Tapi saya tidak berpikir ada bahasa seperti itu, karena method.overloading cenderung ambiguitas, yang tidak dapat diselesaikan oleh kompiler dan yang harus ditangani oleh programmer dengan pemeran eksplisit. Ini tidak dapat dilakukan saat runtime.
sumber
Di Java, jenis informasi dikompilasi dan yang kelebihannya dipanggil ditentukan pada waktu kompilasi.
Berikut ini cuplikan dari
sun.misc.Unsafe
(utilitas untuk Atomics) seperti yang terlihat di editor file kelas Eclipse.karena Anda dapat melihat informasi jenis metode yang dipanggil (saluran 4) termasuk dalam panggilan.
Ini berarti bahwa Anda dapat membuat kompiler java yang mengambil informasi jenis. Misalnya menggunakan notasi seperti itu sumber di atas akan menjadi:
dan para pemain lama akan opsional.
Dalam bahasa-bahasa yang dikompilasi secara statis-diketik lainnya Anda akan melihat setup yang sama di mana kompiler akan memutuskan mana kelebihan akan dipanggil tergantung pada jenis dan memasukkannya dalam mengikat / panggilan.
Pengecualiannya adalah pustaka dinamis C di mana informasi jenis tidak termasuk dan mencoba untuk membuat fungsi kelebihan akan menyebabkan linker mengeluh.
sumber