Overloading adalah menyediakan lebih dari satu tanda tangan (signature) untuk prosedur dengan nama yang sama, sehingga pemanggil menggunakan satu nama untuk kebutuhan yang berdekatan. Tanda tangan sebuah prosedur terdiri atas namanya beserta jumlah, urutan, dan tipe parameternya. Topik ini membahas aturan penyusunan overload, cara compiler memilih versi yang dipanggil, dan kondisi ketika overloading lebih tepat daripada parameter Optional.
Tanda tangan prosedur#
Dua prosedur dapat menggunakan nama yang sama sepanjang tanda tangannya berbeda pada salah satu dari tiga hal, yaitu jumlah parameter, urutan parameter, atau tipe parameter. Compiler menganggap keduanya sebagai satu kelompok prosedur bernama sama dan membedakannya hanya lewat daftar parameternya. Sebaliknya, perbedaan pada tipe nilai kembalian, nama parameter, atau kata kunci seperti ByRef dan Optional tidak dianggap perbedaan tanda tangan, sehingga tidak dapat menjadi dasar overloading.
' tidak-dijalankan
Function HitungTarif(jarak As Integer) As Integer
Return jarak * 4
End Function
Function HitungTarif(jarak As Double) As Double
Return jarak * 4
End FunctionKedua HitungTarif di atas sah karena parameternya bertipe berbeda. Kata kunci Overloads boleh disertakan pada deklarasi di dalam kelas atau modul yang sama, tetapi tidak diwajibkan. Apabila satu deklarasi menyertakannya, maka seluruh deklarasi senama dengannya wajib menyertakannya juga. Kelompok overload boleh mencampur Sub dan Function, dan yang membedakannya tetap parameternya, bukan ada tidaknya nilai kembalian. Aturan ini menjaga kelompok overload tetap konsisten ketika jumlah versinya bertambah.
Contoh overloading pada program loket#
Program berikut menggunakan overloading di dua tempat, yaitu CetakTiket yang dibedakan jumlah parameternya dan HitungTarif yang dibedakan tipe parameternya. Jalankan dengan dotnet run dan perhatikan bahwa pemanggilnya cukup menulis satu nama prosedur untuk semua variasi.
Module Program
' Dua tanda tangan yang berbeda jumlah parameternya
Sub CetakTiket(nomor As Integer)
Console.WriteLine($"Tiket nomor {nomor} (antrean reguler)")
End Sub
Sub CetakTiket(nomor As Integer, kelompok As String)
Console.WriteLine($"Tiket nomor {nomor} (antrean {kelompok})")
End Sub
' Dua tanda tangan yang berbeda tipe parameternya
Function HitungTarif(jarak As Integer) As Integer
Return jarak * 4
End Function
Function HitungTarif(jarak As Double) As Double
Return jarak * 4
End Function
Sub Main()
CetakTiket(12)
CetakTiket(7, "prioritas")
Console.WriteLine($"Tarif jarak 12 km : {HitungTarif(12)}")
Console.WriteLine($"Tarif jarak 7.5 km : {HitungTarif(7.5)}")
End Sub
End ModuleTiket nomor 12 (antrean reguler)
Tiket nomor 7 (antrean prioritas)
Tarif jarak 12 km : 48
Tarif jarak 7.5 km : 30Pemanggilan CetakTiket(12) dilayani versi satu parameter, sedangkan CetakTiket(7, "prioritas") dilayani versi dua parameter. Pada perhitungan tarif, literal 12 bertipe Integer sehingga jatuh ke versi Integer, sedangkan literal 7.5 bertipe Double sehingga jatuh ke versi Double, dan hasil keduanya sesuai tipe kembaliannya masing-masing.
Perhatikan bahwa badan kedua CetakTiket memang berbeda karena kelompok antrean hanya ada pada versi dua parameternya. Badan kedua HitungTarif justru sama persis, karena perkalian tarif berlaku untuk kedua tipe, tetapi keduanya tetap dideklarasikan terpisah karena tanda tangannya berbeda dan tipe kembaliannya ikut berbeda. Nama yang sama jelas memudahkan pemanggil, sebab mencari tarif tidak perlu mengingat dua nama yang berbeda.
Resolusi overload oleh compiler#
Pemilihan versi dilakukan compiler pada saat kompilasi, bukan saat program berjalan, dan proses ini disebut resolusi overload (overload resolution). Compiler mencocokkan daftar argumen dengan setiap tanda tangan, lalu memilih versi yang paling cocok tanpa perlu konversi, dan bila ada konversi, memilih yang seminimal mungkin. Literal 12 jatuh ke versi Integer bukan Double karena kecocokan tipe persisnya lebih diutamakan daripada perluasan tipe.
Apabila dua versi sama-sama cocok dan compiler tidak dapat memilih, kompilasi dihentikan dengan pesan pemanggilan yang mengambang (ambiguous). Kondisi ini jarang terjadi pada kode yang sederhana, tetapi muncul ketika tipe argumen dapat diperluas ke beberapa tanda tangan sekaligus. Perbaikannya dengan menegaskan tipe argumen, misalnya mengganti 12 menjadi 12.0, atau memberi nama prosedur yang berbeda bila maksudnya memang berbeda. Petunjuk praktisnya sederhana, yaitu bila pemanggil harus menebak versi mana yang diinginkan, deklarasi kelompok overload-nya perlu ditata ulang.
' tidak-dijalankan
Function KeMeter(km As Integer) As Integer
Return km * 1000
End Function
Function KeMeter(km As Integer) As Double
Return km * 1000.0
End Function
' error BC30301: keduanya tidak dapat saling di-overload
' karena hanya berbeda tipe kembalianOverloading atau parameter Optional#
Kedua fitur menyelesaikan masalah yang mirip, yaitu satu nama prosedur melayani pemanggilan dengan variasi argumen, tetapi kegunaannya berbeda. Parameter Optional tepat bila logika prosedur tetap sama dan hanya ada nilai yang perlu diisi bila pemanggil tidak mengirimkannya, seperti biaya layanan tiket. Nilai bawaannya juga ikut terdokumentasi pada deklarasi, sehingga pemanggil dapat membacanya langsung dari daftar parameter. Overloading tepat bila variasi argumen membawa perbedaan cara kerja, misalnya menghitung tarif dari Integer yang presisi penuh atau dari Double yang menyimpan pecahan.
| Situasi | Pilihan yang tepat |
|---|---|
| Perlakuan sama, hanya ada nilai bawaan | parameter Optional |
| Tipe argumen berbeda sehingga logika ikut berbeda | overloading |
| Jumlah argumen berbeda dengan tahap kerja yang berbeda | overloading |
| Satu parameter tengah perlu dilompati saat memanggil | argumen bernama |
Tabel di atas bukan aturan mutlak, melainkan patokan yang memudahkan keputusan. Petunjuk yang dapat dipegang adalah memeriksa isi badan prosedurnya, yaitu apabila setiap versi membutuhkan badan yang berbeda, overloading adalah jalurnya, sedangkan apabila satu badan cukup dengan beberapa nilai default, parameter Optional sudah memadai.
Kesalahan umum#
Kesalahan pertama adalah membedakan overload hanya lewat tipe kembalian, sebagaimana contoh KeMeter yang ditolak compiler. Perbaikannya dengan membuat salah satu versi berbeda parameternya, atau memberi nama yang berbeda bila hasilnya memang digunakan untuk tujuan yang berbeda.
Kesalahan kedua adalah membuat dua versi yang parameternya identik setelah pembersihan sintaks. Menambah kata Optional pada parameter versi kedua tidak mengubah tanda tangannya, dan deklarasi itu pun ditolak. Ujilah dengan membaca dua baris deklarasinya bersebelahan, lalu pastikan jumlah, urutan, atau tipe parameternya benar-benar berbeda.
Kesalahan ketiga adalah mengandalkan overloading untuk tipe yang dapat saling diperluas tanpa kejelasan. Kelompok versi Integer dan Double aman untuk argumen literal, tetapi bermasalah ketika argumennya datang dari tipe lain yang dapat diperluas ke keduanya. Sertakan tipe argumen secara eksplisit pada pemanggilan yang ragu agar resolusinya pasti, dan biasakan menyertakan komentar singkat pada setiap versi agar maksudnya tidak perlu ditebak.
Ringkasan#
- Tanda tangan prosedur adalah nama beserta jumlah, urutan, dan tipe parameternya, sedangkan tipe kembalian dan kata kunci parameter tidak termasuk di dalamnya.
- Compiler memilih versi overload pada saat kompilasi dengan mencocokkan argumen terhadap seluruh tanda tangan, dan pemanggilan yang mengambang ditolak sebagai error.
- Gunakan parameter
Optionaluntuk logika yang sama dengan nilai bawaan, sedangkan overloading untuk variasi argumen yang membawa perbedaan cara kerja.
Referensi#
- Procedure Overloading — Microsoft Learn — Aturan overloading beserta daftar yang tidak termasuk tanda tangan.
- Overloads — Microsoft Learn
— Dokumentasi kata kunci
Overloadsdan aturan sukarela-wajibnya. - Overload Resolution — Microsoft Learn — Cara compiler memilih versi yang dipanggil dan penanganan pemanggilan yang mengambang.
- Considerations in Overloading Procedures — Microsoft Learn
— Pertimbangan memilih overloading dibanding parameter
Optional.