Polymorphism dan casting pada Unity c#

Tidak ada komentar

Polymorphism atau Polimorfisme dalam Unity adalah fitur yang memungkinkan kita menggunakan objek dari kelas yang berbeda seolah-olah itu adalah objek dari kelas yang sama. Ini terkait dengan konsep pewarisan dalam pemrograman berorientasi objek.


Fungsi Polymorphism

Polimorfisme memiliki peran yang sangat penting dalam pengembangan permainan menggunakan C# di Unity. Berikut adalah beberapa alasan mengapa polimorfisme sangat penting:

1. Fleksibilitas dan Pergantian:

Polimorfisme memungkinkan penggunaan objek dari kelas yang berbeda seolah-olah mereka berasal dari kelas yang sama. Hal ini memungkinkan penggantian objek dengan objek lain yang memenuhi kontrak yang sama, memberikan fleksibilitas dalam desain dan implementasi.

2. Pewarisan dan Hierarki:

Dalam lingkungan pemrograman berorientasi objek, konsep pewarisan sangat penting. Polimorfisme memungkinkan objek dari kelas yang lebih khusus (seperti Kucing) untuk digunakan dalam konteks yang diharapkan dari kelas yang lebih umum (seperti Hewan).

3. Penggunaan Interface:

Polimorfisme mendukung penggunaan antarmuka (interface) di C#. Dengan antarmuka, Anda dapat membuat kontrak yang harus diikuti oleh kelas-kelas yang berbeda. Objek dari kelas-kelas ini dapat digunakan secara polimorfik melalui antarmuka, memungkinkan implementasi yang berbeda sesuai kebutuhan.

4. Mengurangi Kode Redundan:

Dengan polimorfisme, Anda dapat membuat kode yang lebih bersih dan lebih efisien. Sebagai contoh, jika ada metode yang dapat diimplementasikan secara berbeda oleh berbagai kelas, Anda tidak perlu menuliskan kode yang sama berulang kali.

5. Mempermudah Maintenance:

Dengan memanfaatkan konsep polimorfisme, perubahan pada satu bagian kode tidak selalu memerlukan perubahan pada semua tempat penggunaannya. Ini membuat pemeliharaan dan pengembangan lebih mudah karena perubahan dapat dibatasi pada bagian yang sesuai.

6. Memudahkan Penggunaan Unity:

Unity sendiri menggunakan konsep polimorfisme dalam banyak aspeknya, seperti event handling, serialization, dan bahkan dalam penggunaan komponen-komponen game object.

Penting untuk dipahami dan dikuasai karena polimorfisme adalah salah satu dasar dari pemrograman berorientasi objek dan merupakan alat yang kuat untuk meningkatkan fleksibilitas dan modularitas kode dalam pengembangan game Unity dengan menggunakan bahasa pemrograman C#.


Contoh Dasar Polymorphism

Contoh seperti ini :


{}
public class Mamalia : Hewan
{}
public class Kucing : Mamalia
{}


Bayangkan kita punya tiga kelas: Hewan, Mamalia, dan Kucing. Kucing adalah jenis Mamalia, dan Mamalia adalah jenis Hewan. Dalam polimorfisme, kita dapat melakukan beberapa hal:

  1. Menggunakan objek Kucing seolah-olah itu adalah objek Mamalia:
    - Contohnya, jika kita memiliki objek Kucing, kita dapat memperlakukannya seolah-olah itu adalah objek Mamalia, karena Kucing adalah jenis Mamalia.
  2. Menggunakan objek Mamalia seolah-olah itu adalah objek Hewan:
    - Kita juga dapat menggunakan objek Mamalia seolah-olah itu adalah objek Hewan, karena Mamalia adalah jenis Hewan.
  3. Menggunakan objek Kucing seolah-olah itu adalah objek Hewan :
    - Karena Kucing adalah jenis Mamalia, dan Mamalia adalah jenis Hewan, kita juga dapat memperlakukan objek Kucing seolah-olah itu adalah objek Hewan.

Proses ini disebut "upcasting". Dalam contoh ini, kita dapat "meng-upcast" objek Kucing menjadi objek Mamalia atau objek Hewan. 

Contohnya seperti hubungan "Seekor": Kucing "adalah" Mamalia, dan Mamalia "adalah" Hewan. Dengan polimorfisme, kita dapat dengan mudah mengelola objek dalam hierarki pewarisan dan menggunakan mereka dengan cara yang fleksibel sesuai dengan kebutuhan program public class Hewan.

Penerapan Polymorphism

Dalam istilah praktis, polimorfisme memungkinkan variabel yang merujuk pada instance suatu kelas dapat memiliki tipe yang lebih umum dalam hierarki pewarisan. Mari kita tinjau contoh yang diberikan:

public class Mamalia
{
   public void Berbulu()
   {}
}

public class Kucing : Mamalia
{
   public void Meow()
   {}
}

public class Anjing : Mamalia
{
   public void GukGuk()
   {}
}

public class RescueShelter
{
   public Mamalia[] Mamalias;
   public RescueShelter()
   {
       Mamalias = new Mamalia[2];
       Mamalias[0] = new Kucing();
       Mamalias[1] = new Anjing();        
   }
}

Pada contoh di atas, kita memiliki kelas-kelas `Mamalia`, `Kucing`, dan `Anjing`.

Dimana `Kucing` dan `Anjing` adalah jenis `Mamalia`.

Sedangkan kelas `RescueShelter` yang memiliki array dari tipe `Mamalia`.

Penting untuk dicatat bahwa kita dapat menggunakan polimorfisme di sini. Dua instance khusus, yaitu `Kucing` dan `Anjing`, di-upcast menjadi tipe yang lebih umum, yaitu `Mamalia`. Ini memungkinkan kita untuk menyimpan kedua instance tersebut dalam array `Mamalia[]`.

Namun, meskipun kita dapat memperlakukan instance kelas sebagai instance dari kelas induknya, fungsionalitas dari kelas anak tidak tersedia saat kita melakukannya. Artinya, meskipun kita dapat menyimpan `Kucing` dan `Anjing` dalam array `Mamalia`, kita hanya dapat menggunakan metode yang didefinisikan di kelas `Mamalia`.

Contohnya, kita dapat memanggil metode `Berbulu()` karena metode ini ada di kelas `Mamalia`, namun kita tidak dapat langsung memanggil `Meow()` atau `GukGuk()` karena metode ini hanya ada di kelas `Kucing` dan `Anjing`.

Polimorfisme di sini memberikan kemampuan untuk menyimpan dan merujuk ke instance dengan tipe yang lebih umum, namun fungsionalitas yang sesuai dengan tipe kelas yang lebih khusus tidak dapat diakses langsung melalui tipe yang lebih umum.


Downcasting Pada Kelas Child

Downcasting adalah cara untuk mengakses kemampuan kelas anak (child class) ketika kita memiliki objek yang disimpan dalam array kelas induk (parent class). Ini seperti kita memiliki kucing dan anjing di dalam array hewan, tetapi kita ingin mengakses suara meong dari kucing dan suara guk guk dari anjing.

Contoh Sederhana:

1. Persiapan

Misalkan kita punya kelas-kelas: `Hewan`, `Kucing`, dan `Anjing`.

2. Membuat Objek:

Kita membuat array `Hewan[]` dan menyimpan objek kucing dan anjing di dalamnya.

Hewan[] hewans = new Hewan[2];
    hewans[0] = new Kucing();
    hewans[1] = new Anjing();

3. Dan Error Saat Memanggil Langsung

Saat kita coba memanggil metode `Meow()` pada objek kucing di dalam array secara langsung, kita akan mendapatkan kesalahan kompilasi.

// Compile error.
    // hewans[0].Meow();

4. Downcasting Menggunakan `as`:

Kita menggunakan `as` untuk melakukan downcast dan mengakses kemampuan kucing.

Kucing kucing = hewans[0] as Kucing;
     if (kucing != null) {
         kucing.Meow();
     }

5. Downcasting Menggunakan Cast Langsung:

Kita juga bisa langsung melakukan downcast untuk mengakses kemampuan anjing.

Anjing anjing = (Anjing)hewans[1];
anjing.GukGuk();

#Notes:

  • - Downcasting perlu dilakukan dengan hati-hati, karena jika tidak sesuai, bisa menyebabkan kesalahan saat program dijalankan.
  • - Menggunakan `as` dapat membantu menghindari kesalahan dan memeriksa apakah downcast berhasil atau tidak.
  • - Jika kita yakin downcast akan berhasil, kita bisa menggunakan cast langsung, tapi harus hati-hati agar tidak menyebabkan kesalahan saat runtime.

Menggunakan Pengecekan Tipe Untuk Mengatasi Error

Pada langkah sebelumnya, kita sudah melihat bahwa melakukan memaksakan casting yang salah bisa menyebabkan error. Salah satu cara untuk menghindari ini adalah dengan menggunakan pemeriksaan tipe (type checking) menggunakan kata kunci `is`.

Lihat contoh berikut:

public RescueShelter ()
{
   mamalias = new Mamalia[2];
   mamalias[0] = new Kucing();
   mamalias[1] = new Anjing();
   // Compile error.
   // mamalias[0].Meow();
   
   if(mamalias[0] is Kucing)
   {
       Kucing kucing = mamalias[0] as Kucing;
       kucing.Meow();
   }

   if(mamalias[1] is Anjing)
   {
       Anjing anjing = (Anjing)mamalias[1];
       anjing.GukGuk();
   }
}
kira-kira isinya seperti berikut :

1. Membuat Objek:

Kita membuat array `Mamalia[]` dengan objek kucing dan anjing di dalamnya.

2. Error Prevention dengan Type Checking:

Sebelum melakukan downcast, kita menggunakan ekspresi `is` untuk memeriksa tipe objek. Ini membantu menghindari kesalahan. Jika tipe cocok, kita baru melakukan downcast.

if(mamalias[0] is Kucing)
   {
       Kucing kucing = mamalias[0] as Kucing;
       kucing.Meow();
   }

   if(mamalias[1] is Anjing)
   {
       Anjing anjing = (Anjing)mamalias[1];
       anjing.GukGuk();
   }

3. Fungsi Type Checking:

Ekspresi `mamalias[0] is Kucing` mengembalikan `true` jika objek pada indeks 0 adalah tipe `Kucing`. Ini membantu kita memastikan bahwa kita hanya melakukan downcast jika tipe objek sesuai.

4. Pencegahan Kesalahan:

Dengan melakukan pemeriksaan tipe (`is`) sebelum melakukan downcast, kita mengurangi risiko terjadinya kesalahan dan membuat kode lebih aman dari segi tipe. Jika tipe objek tidak sesuai, maka downcast tidak dilakukan.

Kesimpulan

Untuk menggunakan polimorfisme secara efisien saat mengembangkan game atau aplikasi, Anda dapat mempertimbangkan beberapa praktik terbaik berikut:

1. Desain Hierarki Kelas yang Baik:

Pastikan hierarki kelas Anda terstruktur dengan baik, dengan mempertimbangkan hubungan antara kelas-kelas. Desain yang baik akan mempermudah penggunaan polimorfisme.

2. Gunakan Antarmuka (Interface):

Implementasikan antarmuka untuk menentukan kontrak bersama di antara kelas-kelas. Ini memungkinkan polimorfisme tanpa perlu memikirkan pewarisan. Misalnya, Anda bisa membuat antarmuka seperti `ISound` yang memiliki metode `MakeSound()`, dan berbagai kelas dapat mengimplementasikan antarmuka ini.

3. Pertimbangkan Penggunaan Abstract Class:

Gunakan kelas abstrak jika ada logika umum yang dapat diimplementasikan di kelas induk, namun membutuhkan implementasi spesifik di kelas anak. Ini dapat memudahkan pengelolaan kode.

4. Gunakan Polimorfisme dalam Struktur Game Object:

Di Unity atau lingkungan pengembangan game lainnya, manfaatkan polimorfisme dalam struktur game object. Misalnya, memiliki kelas dasar `GameObject` dan kemudian turunkan untuk menciptakan objek seperti `Player`, `Enemy`, atau `Item`.

5. Pemisahan Logika Bisnis dan Tampilan:

Terapkan konsep pemisahan tanggung jawab (Separation of Concerns) dengan memisahkan logika bisnis dari tampilan. Gunakan polimorfisme untuk memisahkan perilaku dari representasi visual, sehingga dapat lebih mudah dikelola dan dimodifikasi.

6. Pemahaman Tentang Pemeriksaan Tipe:

Pahami penggunaan pemeriksaan tipe (type checking) untuk menghindari kesalahan saat downcasting. Gunakan `is` atau `as` dengan bijak untuk memastikan operasi downcasting aman.

7. Serialisasi dan Deserialisasi dengan Benar:

Jika Anda menggunakan polimorfisme dan perlu menyimpan dan memulihkan objek, pastikan untuk mengimplementasikan serialisasi dan deserialisasi dengan benar. Anda dapat memanfaatkan atribut `[Serializable]`, atau menggunakan metode lain seperti `JsonUtility` di Unity.

8. Uji Coba dan Pemeliharaan Kode:

Lakukan uji coba secara menyeluruh terhadap penggunaan polimorfisme dalam aplikasi atau game Anda. Pastikan bahwa setiap kelas turunan berfungsi sebagaimana mestinya. Selain itu, lakukan pemeliharaan rutin pada kode untuk menjaga kejelasan dan efisiensi.

Dengan memahami dan menerapkan prinsip-prinsip ini, Anda dapat menggunakan polimorfisme secara efisien untuk meningkatkan fleksibilitas, maintenance, dan pengembangan aplikasi atau game Anda.

(sumber : unity.com)

Komentar