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:
bool someFunction(int arg);
bool someFunction(string arg);
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:
dict roomNumber; // some hotels use numbers, some use letters, and some use
// alphanumerical strings. In some languages, built-in dictionary
// types automatically use untyped values for their keys to map to,
// so it makes more sense then to allow for both ints and strings in
// your code.
Nah, bagaimana jika Anda ingin menerapkan someFunction
ke salah satu nomor kamar itu? Anda menyebutnya:
someFunction(roomNumber[someSortOfKey]);
Apakah someFunction(int)
disebut, atau someFunction(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 a string
, 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?
bool stringIsTrue(int arg)
{
if (arg.toString() == "0")
{
return false;
}
else
{
return true;
}
}
bool stringIsTrue(Object arg)
{
if (arg.toString() == "0")
{
return false;
}
else
{
return true;
}
}
bool stringIsTrue(string arg)
{
if (arg == "0")
{
return false;
}
else
{
return true;
}
}
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:
bool stringIsTrue(untyped arg)
{
if (arg.toString() == "0")
{
return false;
}
else
{
return true;
}
}
Tetapi bagaimana jika Anda hanya perlu menggunakan ini untuk int
s dan string
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:
bool appearsToBeFirstFloor(int arg)
{
if (arg.digitAt(0) == 1)
{
return true;
}
else
{
return false;
}
}
bool appearsToBeFirstFloor(string arg)
{
string firstCharacter = arg.characterAt(0);
if (firstCharacter.isDigit())
{
return appearsToBeFirstFloor(int(firstCharacter));
}
else if (firstCharacter.toUpper() == "A")
{
return true;
}
else
{
return false;
}
}
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:
appearsToBeFirstFloor(roomNumber[someSortOfKey]);
// will treat ints and strings differently, without you having to write extra code
// every single spot where the function is being called
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 contoh int
vs. di string
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.