Overloading

Menyediakan lebih dari satu tanda tangan untuk prosedur dengan nama yang sama.

Daftar isi

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.

vb Contoh: dua tanda tangan untuk satu nama
' 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 Function

Kedua 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.

vb OverloadLoket.vb
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 Module
text Keluaran
Tiket nomor 12 (antrean reguler)
Tiket nomor 7 (antrean prioritas)
Tarif jarak 12 km  : 48
Tarif jarak 7.5 km : 30

Pemanggilan 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.

vb Contoh: deklarasi yang ditolak compiler
' 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 kembalian

Overloading 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.

SituasiPilihan yang tepat
Perlakuan sama, hanya ada nilai bawaanparameter Optional
Tipe argumen berbeda sehingga logika ikut berbedaoverloading
Jumlah argumen berbeda dengan tahap kerja yang berbedaoverloading
Satu parameter tengah perlu dilompati saat memanggilargumen 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 Optional untuk logika yang sama dengan nilai bawaan, sedangkan overloading untuk variasi argumen yang membawa perbedaan cara kerja.

Referensi#