Apa itu polimorfisme di Javascript?

91

Saya telah membaca beberapa kemungkinan artikel yang dapat saya temukan di internet tentang polimorfisme . Tapi saya pikir saya tidak bisa memahami arti dan pentingnya. Sebagian besar artikel tidak menjelaskan mengapa itu penting dan bagaimana saya dapat mencapai perilaku polimorfik di OOP (tentu saja dalam JavaScript).

Saya tidak dapat memberikan contoh kode apa pun karena saya belum mendapatkan ide bagaimana menerapkannya, jadi pertanyaan saya ada di bawah ini:

  1. Apa itu?
  2. Mengapa kita membutuhkannya?
  3. Bagaimana itu bekerja?
  4. Bagaimana saya bisa mencapai perilaku polimorfik ini di javascript?

Saya punya contoh ini. Tetapi mudah dimengerti apa yang akan menjadi hasil dari kode ini. Itu tidak memberikan gambaran yang jelas tentang polimorfisme itu sendiri.

function Person(age, weight) {
    this.age = age;
    this.weight = weight;
    this.getInfo = function() {
        return "I am " + this.age + " years old " +
        "and weighs " + this.weight +" kilo.";
    }
}
function Employee(age, weight, salary) {
    this.salary = salary;
    this.age = age;
    this.weight = weight;
    this.getInfo = function() {
        return "I am " + this.age + " years old " +
        "and weighs " + this.weight +" kilo " +
        "and earns " + this.salary + " dollar.";
    }
}

Employee.prototype = new Person();
Employee.prototype.constructor = Employee;
  // The argument, 'obj', can be of any kind
  // which method, getInfo(), to be executed depend on the object
  // that 'obj' refer to.

function showInfo(obj) {
    document.write(obj.getInfo() + "<br>");
}

var person = new Person(50,90);
var employee = new Employee(43,80,50000);
showInfo(person);
showInfo(employee);
AL-zami
sumber
Pertanyaan ini mungkin terlalu luas untuk bekerja dengan baik dengan StackOverflow. Hal terbaik yang dapat kami lakukan adalah menghubungkan Anda dengan penjelasan polimorfisme lainnya. StackOverflow paling baik dalam menjawab pertanyaan spesifik atau klarifikasi tentang masalah tertentu, seperti "Sumber mengatakan polimorfisme adalah XYZ, tapi apa maksud Y?"
Vitruvius
2
kamu tidak membutuhkannya. sama sekali. Anda bahkan tidak memerlukan kelas di JS, dan faktanya, ada banyak paradigma lain yang bisa dibilang lebih baik untuk konstruksi aplikasi. apply / call / bind menghilangkan kebutuhan akan homogenitas, dan dengan soft-object, Anda dapat memodifikasi apa pun agar sesuai dengan kebutuhan Anda tanpa mendekorasi sebelumnya atau mewarisi kasus khusus.
dandavis
1
Polimorfisme tidak hanya terkait dengan OO, dan memiliki banyak arti. Anda mungkin ingin membaca jawaban lain ini di bawah pertanyaan Apakah Polimorfisme Mungkin Tanpa Warisan .
Edwin Dalorzo
Mewarisi biasanya dilakukan secara tidak benar di JavaScript. Untuk membuat instance Parent yang akan digunakan sebagai prototipe Child menunjukkan kurangnya pemahaman tentang peran fungsi konstruktor dan prototipe bermain dalam mendefinisikan dan membuat suatu objek. Informasi lebih lanjut tersedia dalam jawaban ini: stackoverflow.com/a/16063711/1641941
HMR

Jawaban:

99

Polimorfisme adalah salah satu prinsip dari Pemrograman Berorientasi Objek (OOP). Ini adalah praktik merancang objek untuk berbagi perilaku dan mampu menimpa perilaku bersama dengan yang spesifik. Polimorfisme memanfaatkan warisan untuk mewujudkannya.

Dalam OOP semuanya dianggap dimodelkan sebagai objek. Abstraksi ini bisa diturunkan sampai ke mur dan baut untuk mobil, atau hanya sebatas jenis mobil dengan tahun, merek, dan model.

Untuk memiliki skenario mobil polimorfik akan ada jenis mobil dasar, dan kemudian akan ada subkelas yang akan mewarisi dari mobil dan memberikan perilaku mereka sendiri di atas perilaku dasar yang dimiliki mobil. Misalnya, subclass dapat berupa TowTruck yang masih memiliki pembuatan dan model tahun, tetapi mungkin juga memiliki beberapa perilaku dan properti tambahan yang bisa menjadi dasar seperti bendera untuk IsTowing hingga serumit spesifikasi lift.

Kembali ke contoh orang dan karyawan, semua karyawan adalah orang, tetapi semua orang bukan karyawan. Artinya, orang akan menjadi kelas super, dan karyawan menjadi sub kelas. Orang mungkin memiliki usia dan berat, tetapi mereka tidak memiliki gaji. Karyawan adalah manusia sehingga mereka secara inheren memiliki usia dan berat badan, tetapi juga karena mereka adalah karyawan maka mereka akan mendapat gaji.

Jadi untuk memfasilitasi ini, pertama-tama kita akan menulis kelas super (Orang)

function Person(age,weight){
 this.age = age;
 this.weight = weight;
}

Dan kami akan memberi Orang kemampuan untuk membagikan informasi mereka

Person.prototype.getInfo = function(){
 return "I am " + this.age + " years old " +
    "and weighs " + this.weight +" kilo.";
};

Selanjutnya kami ingin memiliki subclass Person, Employee

function Employee(age,weight,salary){
 this.age = age;
 this.weight = weight;
 this.salary = salary;
}
Employee.prototype = new Person();

Dan kami akan mengganti perilaku getInfo dengan menentukan perilaku yang lebih sesuai untuk Karyawan

Employee.prototype.getInfo = function(){
 return "I am " + this.age + " years old " +
    "and weighs " + this.weight +" kilo " +
    "and earns " + this.salary + " dollar.";  
};

Ini dapat digunakan serupa dengan penggunaan kode asli Anda

var person = new Person(50,90);
var employee = new Employee(43,80,50000);

console.log(person.getInfo());
console.log(employee.getInfo());

Namun, tidak banyak yang diperoleh dengan menggunakan warisan di sini karena konstruktor Karyawan sangat mirip dengan person, dan satu-satunya fungsi dalam prototipe sedang diganti. Kekuatan dalam desain polimorfik adalah berbagi perilaku.

Travis J
sumber
2
@ user3138436 - Itu benar. Prototipe rantai akan diinspeksi untuk kejadian pertama getInfoyang akan menjadi milik Karyawan karena rantai tersebut lebih tinggi daripada rantai Orang. Itulah yang saya maksud ketika saya mengatakan "diganti".
Travis J
17
Anda tidak sedang menggunakan konstruktor (Person.call (this, arg)) dan menyetel prototipe Karyawan ke instance Person. Prototipe adalah tempat anggota bersama pergi dan fungsi konstruktor adalah tempat anggota khusus contoh dibuat. Contoh Anda menggunakan kode salin tempel kembali menggunakan fungsi konstruktor dan mewarisi bagian prototipe yang salah (Orang memiliki anggota khusus contoh yang tidak memiliki bisnis di Employee.prototype terutama jika Anda memiliki anggota yang bisa berubah). Info lebih lanjut tentang pewarisan menggunakan fungsi konstruktor dan prototipe di sini: stackoverflow.com/a/16063711/1641941
HMR
3
Untuk Karyawan untuk menggunakan kembali dan memperluas getinfo orang itu bisa dengan mudah dilakukan return Person.prototype.getInfo.call(this) + + "and earns " + this.salary + " dollar.";Alih - alih menyalin kode tempel digunakan kembali.
HMR
3
di sini di mana polimorfisme diterapkan?
albert Jegani
2
@rpeg titik polimorfisme dapat dilihat lebih baik di contoh OPs. fungsi showInfo (); menerima objek umum. polimorfisme sekarang adalah kemampuan untuk bereaksi secara berbeda tergantung pada jenis objeknya. saya pikir jawaban ini tidak membuat ini cukup jelas, karena memanggil getInfo () pada setiap objek tertentu.
Stefan
26

Sebagaimana dijelaskan dalam jawaban lain ini , polimorfisme memiliki interpretasi yang berbeda.

Penjelasan terbaik tentang subjek yang pernah saya baca adalah artikel oleh Luca Cardelli , seorang ahli teori tipe terkenal. Artikel tersebut diberi nama Tentang Memahami Jenis, Abstraksi Data, dan Polimorfisme .

Apa itu?

Cardelli mendefinisikan beberapa jenis polimorfisme dalam artikel ini:

  • Universal
    • parametrik
    • penyertaan
  • AD hoc
    • oveloading
    • paksaan

Mungkin dalam JavaScript, sedikit lebih sulit untuk melihat efek polimorfisme karena jenis polimorfisme yang lebih klasik lebih terlihat dalam sistem tipe statis, sedangkan JavaScript memiliki sistem tipe dinamis.

Jadi, misalnya, tidak ada kelebihan metode atau fungsi atau pemaksaan tipe otomatis pada waktu kompilasi di JavaScript. Dalam bahasa yang dinamis, kami menerima sebagian besar dari hal-hal ini begitu saja. Kami juga tidak memerlukan sesuatu seperti polimorfisme parametrik di JavaScript karena sifat dinamis dari bahasa tersebut.

Namun, JavaScript memiliki bentuk pewarisan tipe yang mengemulasi ide yang sama dari polimorfisme subtipe (diklasifikasikan sebagai polimorfisme inklusi oleh Cardelli di atas) dengan cara yang mirip dengan yang biasanya kita lakukan dalam bahasa pemrograman berorientasi objek lain seperti Java atau C # (seperti yang dijelaskan di jawaban lain yang saya bagikan di atas).

Bentuk polimorfisme lain yang sangat khas dalam bahasa dinamis disebut mengetik bebek .

Merupakan kesalahan untuk percaya bahwa polimorfisme hanya terkait dengan pemrograman berorientasi objek. Model pemrograman lain (fungsional, prosedural, logika, dll.) Menawarkan berbagai bentuk polimorfisme dalam sistem tipenya, mungkin dengan cara yang agak asing bagi yang hanya digunakan untuk OOP.

Mengapa Kami Membutuhkannya?

Polimorfisme memupuk banyak atribut yang baik dalam perangkat lunak, antara lain hal itu mendorong modularitas dan kegunaan kembali serta membuat sistem tipe lebih fleksibel dan dapat ditempa. Tanpanya, akan sangat sulit untuk bernalar tentang tipe. Polimorfisme memastikan bahwa satu jenis dapat diganti dengan yang lain yang kompatibel asalkan memenuhi antarmuka publik, jadi ini juga mendorong penyembunyian informasi dan modularitas.

Bagaimana cara kerjanya?

Ini tidak mudah untuk dijawab, bahasa yang berbeda memiliki cara yang berbeda untuk menerapkannya. Dalam kasus JavaScript, seperti yang disebutkan di atas, Anda akan melihatnya terwujud dalam bentuk hierarki tipe menggunakan pewarisan prototipe dan Anda juga dapat memanfaatkannya menggunakan pengetikan bebek.

Subjeknya agak luas dan Anda membuka dua banyak pertanyaan dalam satu posting. Mungkin yang terbaik adalah Anda mulai dengan membaca makalah Cardelli dan kemudian mencoba memahami polimorfisme terlepas dari bahasa atau paradigma pemrograman apa pun, kemudian Anda akan mulai membuat asosiasi antara konsep teoretis dan bahasa tertentu seperti JavaScript yang ditawarkan untuk mengimplementasikan ide-ide tersebut.

Edwin Dalorzo
sumber
14

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:

// parametric polymorphic functions

const id = x => x;

id(1); // 1
id("foo"); // "foo"

const k = x => y => x;
const k_ = x => y => y;

k(1) ("foo"); // 1
k_(1) ("foo"); // "foo"

const append = x => xs => xs.concat([x]);

append(3) ([1, 2]); // [1, 2, 3]
append("c") (["a", "b"]); // ["a", "b", "c"]

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 mapfungsi:

// Option type
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();
  }
};


// ad-hoc polymorphic function
const map = f => t => t.map(f, t);

// helper/data

const sqr = x => x * x;

const xs = [1, 2, 3];
const x = new Some(5);
const y = new None();

// application

console.log(
  map(sqr) (xs) // [1, 4, 9]
);

console.log(
  map(sqr) (x) // Some {x: 25}
);

console.log(
  map(sqr) (y) // None {}
);

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, speedini dianggap sebagai subtipe weightdan segera setelah kami membandingkan valuesifat - sifatnya, kami secara virtual membandingkan apel dengan jeruk.


sumber
1
Meskipun dalam banyak hal ini lebih akurat (dan tentu saja lebih menyeluruh) daripada jawaban yang diterima, ini tidak memiliki aksesibilitas yang sama: jawaban ini menganggap bahwa penanya sudah terlalu pintar untuk repot dengan pertanyaan :)
Jared Smith
@JaredSmith Saya mencoba meringkas subjek menjadi beberapa paragraf yang mudah dipahami. Tapi semakin dalam saya bor semakin kompleks itu. Saya tidak pernah menemukan sumber yang baik untuk polimorfisme dalam bahasa yang tidak diketik, oleh karena itu menurut saya jawaban ini tetap berharga.
pengeditan sangat meningkatkan aksesibilitas. Adapun kegunaan polimorfisme dalam bahasa dinamis, ada banyak tapi saya kesulitan untuk memikirkan contoh yang baik di JS. Contoh yang lebih baik adalah metode ajaib Python yang memungkinkan tipe yang ditentukan pengguna untuk bekerja dengan fungsi polimorfik seperti len. Atau mungkin conjdari clojure.
Jared Smith
8

apa itu?

Poli = banyak, morfisme = perubahan bentuk atau perilaku.

mengapa kita membutuhkannya?

Dalam pemrograman, Ini digunakan ketika kita ingin antarmuka fungsi (katakanlah fungsi X) cukup fleksibel untuk menerima berbagai jenis atau jumlah parameter. Juga, berdasarkan perubahan jenis parameter atau angka, kita mungkin ingin fungsi X berperilaku berbeda (morfisme).

Bagaimana itu bekerja?

Kami menulis beberapa implementasi fungsi X di mana setiap implementasi menerima jenis parameter atau jumlah parameter yang berbeda. Berdasarkan jenis atau jumlah parameter, kompilator (saat runtime) memutuskan implementasi X mana yang harus dijalankan ketika X dipanggil dari beberapa kode.

bagaimana saya bisa mencapai perilaku polimorfik ini di javascript?

JS bukanlah bahasa yang diketik sehingga sebenarnya tidak dimaksudkan untuk menggunakan konsep OOP seperti polimorfisme. Namun, versi JS yang lebih baru sekarang menyertakan kelas dan ada kemungkinan bahwa polimosfisme bisa mulai masuk akal di JS juga. Jawaban lain memberikan solusi yang menarik.

hadaytullah
sumber
4

Polimorfisme artinya Kemampuan memanggil metode yang sama pada objek yang berbeda dan setiap objek merespon dengan cara yang berbeda disebut POLIMORFISME .

    function Animal(sound){
    this.sound=sound;
    this.speak=function(){
    			return this.sound;
    	}
    }
//one method 
    function showInfo(obj){
    		console.log(obj.speak());
    }
//different objects
    var dog = new Animal("woof");
    var cat = new Animal("meow");
    var cow = new Animal("humbow");
//responds different ways
    showInfo(dog);
    showInfo(cat);
    showInfo(cow);

SooRaj Patil
sumber
2

JavaScript adalah bahasa yang ditafsirkan, bukan bahasa yang dikompilasi.

Waktu kompilasi Polimorfisme (atau polimorfisme statis) Polimorfisme waktu kompilasi tidak lain adalah metode overloading di java, c ++

Jadi metode overloading tidak dimungkinkan dalam javascript.

Tetapi polimorfisme dinamis (waktu proses) adalah polimorfisme yang ada pada waktu proses sehingga penggantian metode dimungkinkan dalam javascript

contoh lain adalah PHP.

Apoorv
sumber