Pemrograman Berorientasi Objek Bab 4 – Subtype Polymorphism / Polymorphism / Polimorfisme Polymorphism Is the ability to create a variable, a function, or an object that has more than one form. The word derives from the Greek "πολυμορφισμός" meaning "having multiple forms". Purpose The purpose of polymorphism is to implement a style of programming called messagepassing in the literature, in which objects of various types define a common interface of operations for users. In strongly typed languages, polymorphism usually means that type A somehow derives from type B, or type C implements an interface that represents type B. In weakly typed languages types are implicitly polymorphic. Usage The primary usage of polymorphism is the ability of objects belonging to different types to respond to method, field, or property calls of the same name, each one according to an appropriate type-specific behavior. The programmer (and the program) does not have to know the exact type of the object in advance, and so the exact behavior is determined at run-time (this is called late binding or dynamic binding) How? Inheritance + Overrriding Sample public class Animal {} public class Cat extends Animal {} public class Dog extends Animal {} Animal catty = new Cat(); // valid, Cat is Animal Animal doggy = new Dog(); // valid, Cat is Animal Cat pussy = new Animal(); // invalid, Animal not only Cat Polymorphism Thingy Virtual Method Invocation (VMI) Polymorphic Arguments Operator instanceof Object Casting Homogeneous & Heterogeneous Collection Virtual Method Invocation Virtual method invocation merupakan suatu hal yang sangat penting dalam konsep polimorfisme. Syarat terjadinya VMI adalah sebelumnya sudah terjadi polymorphism. Pada saat obyek yang sudah dibuat tersebut memanggil overridden method pada parent class, kompiler Java akan melakukan invocation (pemanggilan) terhadap overriding method pada subclass, dimana yang seharusnya dipanggil adalah overridden. VMI Sample public class Animal { private String name; public Animal(String name) { this.setName(name); } public String talk() { return “Animals can't talk (except in cartoons)"; } public void setName(String name) { this.name = name; } public String getName() { return name; } } public class Cat extends Animal { public Cat(String name) { super(name); } public String talk() { return "Meow!"; } } public class Dog extends Animal { public Dog(String name) { super(name); } public String talk() { return "Woof! Woof!"; } } VMI Sample Animal catty = new Cat(“Puss Puss”); S.O.P(catty.talk()); Animal doggy = new Dog(“Guk Gux”); S.O.P(doggy.talk()); What’s Happen? Yang terjadi pada contoh: Obyek catty & doggy mempunyai behavior yang sesuai dengan runtime type bukan compile type. Ketika compile time e adalah Animal. Ketika runtime e adalah Cat and Dog. Jadi : catty & doggy mengakses field milik Animal, tetapi catty mengakses method milik Cat, doggy mengakses method milik Dog Ingat catty & doggy tipe datanya Animal What’s Happen? (Cont`) Bagaimana dengan konstruktor yang dijalankan? Pada pembentukan Animal catty = new Cat(); Pertama kali akan menjalankan konstruktor Cat, ketika ketemu super() maka akan menjalankan konstruktor Animal (superclass), setelah semua statement dieksekusi baru kemudian menjalankan konstruktor Cat (subclass). Polymorphic Arguments Polymorphic arguments adalah tipe data suatu argumen pada suatu method yang bisa menerima suatu nilai yang bertipe subclass-nya. Sample: public class PrintAnimal { public void print(Animal a) { S.O.P(a.getName() + " says: " + a.talk()); } p.s.v main(String[] args) { Cat catty = new Cat(“Puss Puss”); Dog doggy = new Dog(“Guk Gux”); PrintAnimal pa = new PrintAnimal(); pa.print(catty); pa.print(doggy); } } Why PA? Mengefisienkan pembuatan program Misal Animal mempunyai banyak subclass. Maka kita harus mendefinisikan semua method yang menangani behavior dari masing-masing subclass. Dengan adanya polymorphic arguments kita cukup mendefinisikan satu method saja yang bisa digunakan untuk menangani behavior semua subclass. No PA public class PrintAnimal { public void print(Cat a) { S.O.P(a.getName() + " says: " + a.talk()); } public void print(Dog a) { S.O.P(a.getName() + " says: " + a.talk()); } } Operator instanceof Digunakan untuk mengetahui tipe data asal dari objek polimorphic Mengembalikan boolean T/F <var name> instanceof <class name> public class PrintAnimal { public void print(Animal a) { if (a instanceof Cat) { S.O.P(“A cat called ” + a.getName() + " says: " + a.talk()); } else if (a instanceof Dog) { S.O.P(“A dog called ” + a.getName() + " says: " + a.talk()); } } } Object Casting Seringkali pemakaian instanceof diikuti dengan casting object dari tipe parameter ke tipe asal. Tanpa adanya casting objek, maka nilai yang akan kita pakai setelah proses instanceof masih bertipe parent class-nya, sehingga jika ia perlu dipakai maka ia harus di casting dulu ke tipe subclass-nya. Method yang merupakan milik subclass juga tidak bisa diakses tanpa adanya casting. How? public void print(Animal a) { if (a instanceof Cat) { S.O.P(“A cat called ” + a.getName() + " says: " + a.talk()); Cat cat = (Cat) a; // call defined Cat’s method in Cat class } else if (a instanceof Dog) { S.O.P(“A dog called ” + a.getName() + " says: " + a.talk()); Dog dog = (Dog) a; // call defined Dog’s method in Dog class } } Homogeneous & Heterogeneous Collection Dengan munculnya konsep Polymorphism, muncul pula sebuah konsep yang disebut Heterogeneous Collection dan Homogeneous Collection. Sebuah collection yang sebelumnya merupakan kumpulan dari objek sejenis, sekarang “dipisah” berdasarkan keberagaman tipe data isi kumpulannya. Homogeneous Collection Homogeneous collection adalah kumpulan objek yang memiliki tipe data yang sama. Sample: Cat[] cats = new Cat[5]; cats[0] = new Cat(“missy”); cats[1] = new Cat(“sissy”); dst Heterogeneous Collection Heterogeneous collection adalah kumpulan objek yang memiliki tipe data yang berbeda – beda. Sample: Animal[] animals = new Animal[5]; animals[0] = new Cat(“missy”); animals[1] = new Dog(“doggy”); dst