-->

Pemrograman #6 - Polimorfisme



Polimorfisme (Polymorphism)

Polimorfisme termasuk salah satu konsep yang penting dari pemrogramman berorintasi objek. kata polimorfisme tersusun atas dua kata dasar yaitu poly dan morph, dimana poly berarti banyak dan morph berarti bentuk. jadi polimorfisme berarti memiliki berbagai bentuk. Biasanya polimorfisme terjadi ketika ada hirarki kelas yang mana kelas-kelas tersebut terjadi hubungan pewarisan.

Polimorfisme bisa berarti satu fungsi dengan nama yang sama tapi diakses dalam bentuk yang berbeda baik dalam kelas yang sama maupun kelas yang berbeda pula.

Polimorfisme pada C++ dapat berarti bahwa panggilan untuk fungsi member akan menyebabkan fungsi berbeda yang dijalankan tergantung pada jenis objek yang memanggilnya.

Secara umum polimorfisme terbagi atas tiga jenis yang dilihat dari jenis fundamentalnya yang berbeda antara lain: Ad Hoc Polymorphism, Inclusion Polymorphism, dan Parametric Polymorphism.

Ad Hoc Polymorphism

Istilah ad hoc polimorfisme merujuk kepada polimorfik fungsi yang dapat diterapkan untuk argumen dari berbagai jenis, tapi juga mempunyai perilaku yang berbeda tergantung pada jenis argumen yang diterapkan. Jika fungsi menunjukan implementasi yang berbeda dan berpotensi heterogen yang secara individu ditentukan oleh jenis dan kombinasi, inilah yang dimaksud dengan ad hoc polimorfisme.

Polimorfisme jenis ini sudah didukung oleh banyak bahasa pemrogramman. polimorfisme jenis ini menggunakan fungsi yang banyak dikenal dengan nama fungsi “Overloading”. fungsi overloading banyak ditemukan pada konstruktor didalam sebuah kelas.

Secara teknis fungsi overloading memiliki nama yang sama hanya saja berbeda dalam parameternya baik nama maupun tipe yang digunakan.

Berikut contoh sederhana dari fungsi overloading pada ad hoc polimorfisme:
/* Berkas Overloading.cpp */
#include <iostream>
using namespace std;

class PrintData {
  public:
    PrintData() {}
    void printOutput() { // Fungsi Overloading
      cout << "Welcome..." << endl;
    }
    void printOutput(string data) { // Fungsi Overloading
      cout << data << endl;
    }

    void printOutput(int data) { // Fungsi Overloading
      cout << data << endl;
    }         
    ~PrintData() {}
};

int main() {
  PrintData print;
  
  print.printOutput();
  print.printOutput("09.51.0045");
  print.printOutput(36);
  return 0;
}
Dari contoh diatas dapat dilihat fungsi printOutput()dapat ditulis sebanyak tiga kali dengan parameter yang berbeda-beda. Hal inilah yang dikenal dengan nama fungsi overloading yang merupakan bagian dari konsep pemrogramman berorientasi objek yaitu polimorfisme.

Inclusion Polymorphism

Polimorfisme ini juga dikenal dengan nama lain yaitu subtyping, adalah sebuah konsep dimana sebuah nama mungkin menunjukkan contoh berbagai kelas yang berbeda selama mereka berhubungan dengan beberapa kelas-kelas dasar.

Jika sebuah kelas mewarisikan kelas yang diturunkan dan memberikan lagi definisi untuk salah satu fungsi kelas dasar kedalam kelas yang diturunkan, maka fungsi tersebut dapat dikatakan overridden, dan polimorfisme jenis ini menggunakan fungsi yang banyak dikenal dengan nama fungsi “Overriding”.

Polimorfisme jenis ini memiliki beberapa bentuk dan satu kesamaan. Dalam pewarisan polimorfisme jenis ini dilakukan dengan menggunakan fungsi overriding. dalam artian ketika kelas dasar dan kelas turunan memiliki fungsi member dengan deklarasi yang sama tetapi berbeda definisi.
Untuk dapat membuat fungsi overriding diperlukan beberapa persyaratan antara lain:

  • Hubungan pewarisan harus terjadi. fungsi overriding tidak dapat dilakukan pada kelas biasa. Untuk itulah dibutuhkan kelas turunan (derived class) dan kelas dasar (base class).
  • Fungsi yang didefinisikan ulang harus sama persis, deklarasi baik di kelas dasar maupun kelas turunan harus memiliki nama yang sama, kembalian(return type) yang sama, termasuk juga jumlah dan tipe parameter yang sama.

Fungsi yang didefinisikan ulang harus persis sama Deklarasi dasar dan turunan kelas, yang berarti nama yang sama, sama kembali jenis dan daftar parameter yang sama.

Berikut contoh sederhana dari fungsi overriding pada inclusion polimorfisme:
/* Berkas Overriding.cpp */
#include <iostream>
using namespace std;

class PrintData {
  public:
    PrintData() {}
    void printOutput() { // Fungsi Overriding
      cout << "Welcome..." << endl;
    }
    ~PrintData() {}
};

class Student: public PrintData {
  protected:
    string nim;
    string name;
    string gender;
  public : 
    Student(string cNim, string cName, string cGender): 
      nim{cNim}, 
        name{cName},
      gender{cGender} {}
    void printOutput() { // Fungsi Overriding
      cout << "The Student Id is " << nim << endl;
    }
    ~Student() {}
};

class Staff: public PrintData {
  private:
    string nip;
    string name;
  public:
    Staff(string cNip, string cName): 
      nip{cNip}, 
        name{cName} {}
    void printOutput() { // Fungsi Overriding
      cout << "The Staff Id is " << nip << endl;
    }
    ~Staff() {}
};

int main() {
  PrintData data;
  Student student("09.51.0045", "Fai Filza", "M");
  Staff staff("555084", "Fai Filza");
  
  data.printOutput();
  student.printOutput();
  staff.printOutput();
  return 0;
}
Dari contoh diatas dapat dilihat fungsi printOutput() dapat ditulis sebanyak tiga kali dengan nama yang sama, nilai kembalian yang sama, bahkan dengan komposisi parameter yang sama pula. Hanya saja fungsi tersebut ditulis dikelas-kelas yang berbeda. Hal inilah yang dikenal dengan nama fungsi overriding yang merupakan bagian dari konsep pemrogramman berorientasi objek yaitu polimorfisme.

Namun pada fungsi overriding terdapat kasus yang muncul apabila menggunakan pointer sebagai objek dari kelas. setelah dilakukan perubahan pada fungsi main()yang ada pada berkas Overriding.cpp yaitu penambahan objek pointer. Untuk lebih jelasnya perhatikan potongan kode perubahan main() dibawah ini:
int main() {
  PrintData *pData1, *pData2;
  Student student("09.51.0045", "Fai Filza", "M");
  Staff staff("555084", "Fai Filza");
  pData1 = &student;
  pData2 = &staff;
  
  pData1->printOutput();
  pData2->printOutput();
  return 0;
}
Dari contoh kasus diatas dapat dilihat fungsi printOutput() pada objek student dan objek staff di akses melewati sebuah pointer dari kelas PrintData. Ini jika dijalankan (kompilasi) maka fungsi yang diakses bukanlah fungsi yang ada pada objek student maupun objek staff melainkan fungsi printOutput()dari kelas PrintData.

Alasan untuk output yang kurang tepat adalah ketika fungsi printOutput()dipanggil sudah diset pertama kali oleh kompilator sebagai versi yang didefinisikan pada kelas dasar. Hal ini disebut static resolution dari fungsi yang dipanggil, atau static linkage – sebuah fungsi yang sudah ditetapkan sebelum program dieksekusi. Ini juga terkadang disebut early binding karena fungsi printOutput()di set selama kompilasi terhadap program.

Untuk mengatasi masalah ini maka harus diadakan sedikit perubahan pada kelas dasar dalam hal ini adalah PrintData. Perubahan dilakukan pada fungsi overriding yaitu fungsi printOutput() dengan menambahkan kata kunci virtual. Berikut hasil perubahan yang dilakukan terhadap kelas dasar :
class PrintData {
  public:
    PrintData() {}
    // Penambahan kata kunci virtual pada kelas dasar
    virtual void printOutput() {  // Fungsi Overriding
      cout << "Welcome..." << endl;
    }
    ~PrintData() {}
};
Fungsi virtual adalah sebuah fungsi yang biasanya diletakkan didalam kelas dasar yang dideklarasikan dengan menggunakan kata kunci virtual. Dengan adanya fungsi virtual ini maka akan memberikan sinyal kepada kompilator untuk menyatakan tidak terdapat static linkage untuk fungsi tersebut. Sehingga ketika diakses melewati pointer, fungsi serupa dengan versi lain yang terdapat pada kelas turunan tetap dapat diakses.

Ketika menginginkan pemilihan fungsi yang akan dipanggil pada poin tertentu dalam program, maka harus didasarkan pada jenis objek yang dipanggil (called). Urutan operasi inilah yang disebut sebagai dynamic linkage, atau late binding.


Parametric Polymorphism

Polimorfisme parametik memungkinkan fungsi atau tipe data ditulis secara generically, sehingga bisa menangani nilai-nilai identik tanpa harus ketergantungan pada jenisnya. Polimorfisme parametrik adalah cara untuk membuat bahasa lebih ekspresif, sementara tetap mempertahankan penuh type-safety.

Konsep polimorfisme parametric berlaku untuk tipe data dan fungsi. Sebuah fungsi dapat mengevaluasi atau diterapakan untuk nilai-nilai dari berbagai jenis yang mana dikenal sebagai fungsi polimorfik. Sebuah tipe data yang dapat muncul untuk menjadi tipe generalized.

Polimorfisme parametik sudah tersedia di beberapa bahasa pemrogramman yang sudah berorientasi objek. didalam bahasa JAVA ini kenal dengan nama Generics. dan dalam bahasa C++ dikenal dengan nama Templates. Untuk templates sendiri akan lebih dibahas khusus pada pokok bahasan selanjutnya.
Load Comments

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel