Apa tujuan polimorfisme?
Polimorfisme membuat sistem tipe statis lebih fleksibel tanpa kehilangan keamanan tipe statis (signifikan) dengan melonggarkan kondisi kesetaraan tipe. Buktinya tetap bahwa program hanya akan berjalan jika tidak mengandung kesalahan jenis apa pun.
Fungsi polimorfik atau tipe data lebih umum daripada fungsi monomorfik, karena dapat digunakan dalam skenario yang lebih luas. Dalam pengertian ini polimorfisme mewakili gagasan generalisasi dalam bahasa yang diketik secara ketat.
Bagaimana ini berlaku untuk Javascript?
Javascript memiliki sistem tipe dinamis yang lemah. Sistem tipe seperti itu setara dengan sistem tipe ketat yang hanya berisi satu tipe. Kita dapat menganggap tipe seperti itu sebagai tipe gabungan yang besar (sintaks semu):
type T =
| Undefined
| Null
| Number
| String
| Boolean
| Symbol
| Object
| Array
| Map
| ...
Setiap nilai akan dikaitkan dengan salah satu dari alternatif jenis ini pada waktu proses. Dan karena Javascript diketik lemah, setiap nilai dapat mengubah jenisnya beberapa kali.
Jika kita mengambil perspektif teoritis tipe dan menganggap bahwa hanya ada satu tipe, kita dapat mengatakan dengan pasti bahwa sistem tipe Javascript tidak memiliki pengertian polimorfisme. Sebagai gantinya kami memiliki pengetikan bebek dan pemaksaan tipe implisit.
Tapi ini seharusnya tidak membuat kita berpikir tentang tipe dalam program kita. Karena kurangnya jenis dalam Javascript, kami perlu menyimpulkannya selama proses pengkodean. Pikiran kita harus berdiri di atas kompiler yang hilang, yaitu segera setelah kita melihat sebuah program, kita harus mengenali tidak hanya algoritme, tetapi juga jenis yang mendasarinya (mungkin polimorfik). Jenis ini akan membantu kami membangun program yang lebih andal dan lebih kuat.
Untuk melakukan ini dengan benar, saya akan memberi Anda gambaran umum tentang manifestasi polimorfisme yang paling umum.
Polimorfisme parametrik (alias generik)
Polimorfisme parametrik mengatakan bahwa tipe yang berbeda dapat dipertukarkan karena tipe tidak penting sama sekali. Sebuah fungsi yang mendefinisikan satu atau lebih parameter dari tipe polimorfik parametrik tidak boleh mengetahui apapun tentang argumen yang sesuai tapi memperlakukan semuanya sama, karena mereka dapat mengadopsi tipe apapun. Ini cukup membatasi, karena fungsi seperti itu hanya dapat bekerja dengan properti argumennya yang bukan bagian datanya:
const id = x => x;
id(1);
id("foo");
const k = x => y => x;
const k_ = x => y => y;
k(1) ("foo");
k_(1) ("foo");
const append = x => xs => xs.concat([x]);
append(3) ([1, 2]);
append("c") (["a", "b"]);
Polimorfisme ad-hoc (alias kelebihan beban)
Polimorfisme ad-hoc mengatakan bahwa tipe yang berbeda setara untuk tujuan tertentu saja. Untuk menjadi ekuivalen dalam pengertian ini, tipe harus mengimplementasikan sekumpulan fungsi yang spesifik untuk tujuan itu. Fungsi yang mendefinisikan satu atau lebih parameter dari tipe polimorfik ad-hoc kemudian perlu mengetahui kumpulan fungsi mana yang terkait dengan setiap argumennya.
Polimorfisme ad-hoc membuat fungsi kompatibel dengan domain tipe yang lebih besar. Contoh berikut mengilustrasikan tujuan "map-over" dan bagaimana tipe dapat mengimplementasikan batasan ini. Alih-alih satu set fungsi, batasan "mappable" hanya menyertakan satu map
fungsi:
class Option {
cata(pattern, option) {
return pattern[option.constructor.name](option.x);
}
map(f, opt) {
return this.cata({Some: x => new Some(f(x)), None: () => this}, opt);
}
};
class Some extends Option {
constructor(x) {
super(x);
this.x = x;
}
};
class None extends Option {
constructor() {
super();
}
};
const map = f => t => t.map(f, t);
const sqr = x => x * x;
const xs = [1, 2, 3];
const x = new Some(5);
const y = new None();
console.log(
map(sqr) (xs)
);
console.log(
map(sqr) (x)
);
console.log(
map(sqr) (y)
);
Polimorfisme subtipe
Karena jawaban lain sudah mencakup polimorfisme subtipe, saya melewatkannya.
Polimorfisme struktural (alias subtipe strutrual)
Polimorfisme struktural mengatakan bahwa tipe yang berbeda adalah ekuivalen, jika mereka mengandung struktur yang sama sedemikian rupa, bahwa satu tipe memiliki semua properti dari tipe lainnya tetapi dapat mencakup properti tambahan. Karena itu, polimorfisme struktural adalah pengetikan bebek pada waktu penyusunan dan tentunya menawarkan beberapa tambahan keamanan jenis. Tetapi dengan mengklaim bahwa dua nilai memiliki tipe yang sama hanya karena keduanya berbagi beberapa properti, itu sepenuhnya mengabaikan tingkat nilai semantik:
const weight = {value: 90, foo: true};
const speed = {value: 90, foo: false, bar: [1, 2, 3]};
Sayangnya, speed
ini dianggap sebagai subtipe weight
dan segera setelah kami membandingkan value
sifat - sifatnya, kami secara virtual membandingkan apel dengan jeruk.