Pelajaran modul (2/2)
Polimorfisme dan Kelas Abstrak
Polimorfisme dan kelas abstrak adalah konsep pemrograman berorientasi objek tingkat lanjut yang memungkinkan kita menulis kode yang fleksibel dan dapat diperluas, tidak bergantung pada implementasi tertentu.
Polimorfisme
Istilah polimorfisme (banyak bentuk) mengacu pada kemampuan untuk memperlakukan objek dari kelas yang berbeda seolah-olah mereka termasuk dalam tipe yang sama. Di Java, variabel referensi superkelas dapat menyimpan referensi ke objek dari subkelas mana pun.
class Animal {
public void makeSound() {
System.out.println("Verso...");
}
}
class Dog extends Animal {
public void makeSound() {
System.out.println("Woof");
}
}
class Cat extends Animal {
public void makeSound() {
System.out.println("Miao");
}
}Berkat polimorfisme, kita dapat melakukan ini:
Animal myAnimal1 = new Dog(); // Polymorphism
Animal myAnimal2 = new Cat(); // Polymorphism
myAnimal1.makeSound(); // Executes Dog's method (Woof)
myAnimal2.makeSound(); // Executes Cat's method (Miao)Keputusan mengenai metode mana yang akan dipanggil dibuat pada saat runtime (Late Binding atau pengiriman dinamis) berdasarkan objek sebenarnya, bukan tipe variabel referensi.
Kelas Abstrak (abstract)
Kelas abstrak adalah kelas yang ditandai dengan kata kunci abstract yang tidak dapat dibuat instance-nya secara langsung (Anda tidak dapat melakukan new MyAbstractClass()). Ini berfungsi sebagai "templat parsial" untuk kelas lain.
Metode Abstrak
Kelas abstrak dapat berisi metode abstrak: metode yang dideklarasikan tanpa isi (tanpa kurung kurawal dan tanpa kode), diakhiri dengan titik koma. Subkelas non-abstrak diperlukan untuk mengimplementasikan semua metode abstrak yang diwarisi.
abstract class Shape {
String color;
// Abstract method (no body)
public abstract double getArea();
}
class Circle extends Shape {
double radius;
public Circle(double radius) {
this.radius = radius;
}
// Required to implement getArea
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}Pengikatan Dinamis / Pengikatan Terlambat
Bagaimana Java mengetahui metode mana yang harus dijalankan saat runtime? Proses ini dikenal sebagai Late Binding (atau Dynamic Binding). Tidak seperti kelebihan beban (yang diselesaikan pada waktu kompilasi), kompiler tidak mengetahui metode spesifik mana yang akan dieksekusi. Sebaliknya, ini menghasilkan instruksi panggilan umum. Saat runtime, Java Virtual Machine (JVM) memeriksa objek sebenarnya di memori dan memanggil implementasi metode yang ditentukan dalam kelas objek tersebut.
Kelas Abstrak dan Implementasinya Hilang
Jika suatu subkelas mewarisi dari kelas abstrak, ia mempunyai dua opsi:
- Menerapkan semua metode abstrak: dalam hal ini, subkelas dapat berupa kelas normal (konkret) dan dapat dibuat instance-nya.
- Deklarasikan dirinya abstrak: jika subkelas tidak menyediakan implementasi untuk semua metode abstrak yang diwarisi, subkelas tersebut juga harus dideklarasikan dengan kata kunci
abstract.
abstract class Animal {
public abstract void makeSound();
}
// This class MUST be abstract because it does not implement makeSound()
abstract class Canine extends Animal {
// Inherits makeSound() but does not implement it
}Cobalah sendiri
Deklarasikan variabel s bertipe Bentuk dan tetapkan objek Lingkaran baru ke dalamnya menggunakan polimorfisme.
Tunjukkan petunjuk
Tulis `Bentuk s = lingkaran baru();` untuk menggunakan tipe dasar sebagai tipe referensi.
Solusi tersedia setelah 3 upaya
Jadikan kelas Shape abstrak dan tambahkan metode abstrak ganda getArea(). Kemudian selesaikan Square sehingga memperluas Shape dan mengimplementasikan getArea() sisi kembali * sisi.
Tunjukkan petunjuk
Deklarasikan `getArea ganda abstrak publik();` dalam Shape. Di Kotak, tambahkan `@Override public double getArea() { return side * side; }`.
Solusi tersedia setelah 3 upaya
Deklarasikan dalam metode utama sebuah array bertipe Shape[] yang berisi objek Lingkaran dengan radius 2,0 dan objek Kotak dengan sisi 3,0. Kemudian, gunakan loop (for atau for-each) untuk mencetak luas setiap bentuk dengan memanggil metode getArea().
Tunjukkan petunjuk
Deklarasikan array dengan `Bentuk[] bentuk = { lingkaran baru(2.0), Kotak baru(3.0) };` dan ulangi menggunakan `untuk (Bentuk s : bentuk)` mencetak `s.getArea()`.
Solusi tersedia setelah 3 upaya