Kelas melambangkan cetak biru objek yang memiliki kesamaan struktuk dan perilaku. Kelas menentukan struktur suatu objek melalui variabel yang terkandung dalam setiap objek, dan menentukan perilaku melalui metode instansi yang merupakan perilaku suatu objek.
Ide utama dari pemrograman berorientasi objek -- yang membedakannya dari pemrograman tradisional -- adalah menciptakan kelas yang memiliki hanya beberapa (tidak semua) struktur dan perilaku. Kemiripan ini diekspresikan dalam bentuk pewarisan dan polimorfisme (perubahan bentuk).
Istilah pewarisan berarti suatu kelas bisa mewariskan sebagian atau keseluruhan struktur dan perilaku kelas lain. Jika kelas B adalah kelas turunan dari kelas A, maka kita bisa juga menyebut kelas A adalah kelas super dari kelas B. Kelas turunan bisa memiliki struktur atau perilaku tambahan dari kelas supernya. Atau bahkan kelas turunan bisa mengubah atau mengganti perilaku kelas supernya. Hubungan antara kelas turunan dan kelas super sering dilukiskan dalam bentuk diagram di mana kelas turunan digambarkan di bawah kelas supernya, dan dihubungkan dengan garis penghubung dengan tanda segitiga yang diletakkan di dekat kelas supernya.
Dalam bahasa Java, ketika kita membuat suatu kelas, kita bisa menyatakan bahwa kelas tersebut merupakan kelas turunan dari kelas lain. Jika kita buat kelas yang bernama "B" dan kita ingin kelas ini menjadi kelas turunan dari kelas "A", kita akan tulis dalam bentuk :
class B extends A {
.
. // tambahan atau perubahan
. // struktur dan perilaku dari kelas A
.
}
Beberapa kelas dapat menurunkan kelas yang sama. Kelas-kelas turunan ini masing-masing disebut kelas saudara, yaitu diwariskan dari satu kelas super yang sama. Struktur dan perilaku kelas super ini akan dimiliki oleh masing-masing turunannya. Pada diagram berikut, kelas B, C, dan D adalah kelas saudara. Pewarisan juga bisa dilakukan beberapa kali, atau suatu kelas bisa memiliki cucu, buyut, dan seterusnya. Pada diagram, kelas E merupakan kelas turunan kelas D, sehingga kelas E adalah "cucu" dari kelas A. Kelas E masih bisa disebut turunan dari kelas A, walaupun bukan merupakan turunan langsungnya.
Mari kita buat sebuah contoh. Kita akan membuat program yang berhubungan dengan kendaraan bermotor, yang meliputi mobil, truk, dan motor. Program tersebut memiliki kelas yang dinamakan Kendaraan yang melambangkan semua jenis kendaraan bermotor. Kelas Kendaraan memiliki variabel instansi seperti nomorPolisi dan pemilik dan metode instansi yang bernama gantiPemilik. Variabel dan metode instansi ini bisa digunakan oleh segala jenis kendaraan bermotor.
Ada 3 kelas turunannya yaitu Mobil, Truk dan Motor yang akan menyimpan variabel dan metode khusus untuk setiap jenis kendaraan. Kelas Mobil misalnya memiliki variabel jumlahPintu, kelas Truk memiliki variabel jumlahRoda, dan kelas Motor memiliki variabel jumlahTak. Kelas-kelas ini bisa dideklarasikan dalam Java dalam bentuk
class Kendaraan {
int nomorPolisi;
Orang pemilik; // (anggap kelas Orang telah dibuat sebelumnya)
void gantiPemilik(Orang pemilikBaru) {
. . .
}
. . .
}
class Mobil extends Kendaraan {
int jumlahPintu;
. . .
}
class Truk extends Kendaraan {
int jumlahRoda;
. . .
}
class Motor extends Kendaraan {
int jumlahTak; // 2-tak atau 4-tak
. . .
}
Anggap mobilku adalah variabel dengan tipe Mobil akan dideklarasikan dan diinisialisasi dengan pernyataan berikut
Mobil mobilku = new Mobil();
Dengan deklarasi seperti ini, maka program akan bisa mengakses mobilku.jumlahPintu, karena jumlahPintu adalah variabel instansi dari kelas Mobil. Akan tetapi karena kelas Mobil merupakan turunan dari kelas Kendaraan, maka mobil ini juga memiliki stuktur dan perilaku dari kendaraan. Artinya program juga bisa mengakses mobilku.nomorPolisi, mobilku.pemilik, dan menjalankan metode mobilku.gantiPemilik()
Dalam dunia nyata mobil, truk dan motor memang kendaraan (bukan hanya pada program). Dalam arti objek yang memiliki tipe Mobil atau Truk atau Motor juga secara otomatis objek bertipe Kendaraan. Fakta penting berikutnya :
Variabel yang dapat diisi referensi ke objek suatu kelas A juga dapat diisi referensi ke objek kelas turunan dari kelas A.
Efek praktis dari penyataan ini adalah, objek dengan tipe Mobil dapat diisi ke dalam variabel bertipe Kendaraan, atau dengan kata lain perintah berikut adalah valid
Kendaraan kendaraanku = mobilku;
atau bahkan juga perintah berikut
Kendaraan kendaraanku = new Mobil();
Setelah pernyataan di atas, variabel kendaraanku berisi referensi ke objek Kendaraan, yang kebetulan merupakan instansi dari kelas turunannya, yaitu kelas Mobil. Objek akan "mengingat" bahwa yang disimpan dalam variabel tersebut adalah objek bertipe Mobil, bukan Kendaraan. Informasi tentang objek apa yang disimpan pada memori ikut disertakan bersama objek tersebut, sehingga variabel yang bertipe Kendaraan akan tahu dengan pasti tipe objek yang dirujuknya. Kita juga dapat menguji jenis objek yang disimpan suatu variabel dengan menggunakan operator instanceof. Misalnya
if (kendaraanku instanceof Mobil) { ... }
menguji apakah objek yang dirujuk pada variabel kendaraanku merupakan objek bertipe Mobil.
Kebalikannya, pernyataan berikut tidak bisa dilakukan
mobilku = kendaraanku;
karena kendaraanku bisa bertipe objek lain seperti Truk atau Motor. Apabila kita tahu persis bahwa kendaraanku bertipe Mobil, kita bisa menggunakan casting, untuk memberi tahu komputer untuk memperlakukan variabel kendaraanku memiliki tipe Mobil. Jadi kita bisa gunakan perintah
mobilku = (Mobil)kendaraanku;
Atau kita juga bisa mengakses ((Mobil)kendaraanku).jumlahPintu. Mari kita gunakan kelas ini dalam program, dan kita ingin mencetak informasi yang sesuai dengan suatu kendaraan. Misalnya:
System.out.println("Data Kendaraan:");
System.out.println("Nomor polisi: " + kendaraanku.nomorPolisi);
if (kendaraanku instanceof Mobil)
System.out.println("Jenis kendaraan: Mobil");
Mobil m = (Mobil)kendaraanku;
System.out.println("Jumlah pintu: " + m.jumlahPintu);
}
else if (kendaraanku instanceof Truk) {
System.out.println("Jenis kendaraan: Truk");
Truk t = (Truk)kendaraanku ;
System.out.println("Jumlah roda: " + t.jumlahRoda);
}
else if (kendaraanku instanceof Motor) {
System.out.println("Jenis kendaraan: Motor");
Motor sm = (Motor)kendaraanku ;
System.out.println("Jumlah tak: " + sm.jumlahTak);
}
Lihat bahwa untuk setiap jenis objek, komputer akan menguji satu per satu tipe objek yang disimpan dalam kendaraanku. Jika kendaraanku[code] merujuk pada objek bertipe Truk maka casting [code](Mobil)kendaraanku akan menampilkan pesan kesalahan. Contoh lain, mari kita buat program untuk menggambar suatu bentuk geometri pada layar. Misalnya bentuk geometri tersebut terdiri dari persegi panjang, oval, dan kotak bersudut lingkar dengan berbagai warna.
Kelas yang akan kita buat adalah PersegiPanjang, Oval, dan KotakLingkar. Ketiga kelas tersebut memiliki kelas super yang sama yang disebut BentukGeometris. Kelas BentukGeometris memiliki variabel instansi warna, lokasi, dan ukuran. Untuk mengganti warna kita bisa mengganti variabel instansi warna pada kelas ini, kemudian menjalankan metode instansi gambar() untuk menggambar bentuk tersebut dengan warna baru:
class BentukGeometris {
Color warna; // Warna suatu bentuk geometri
// (Kelas Color diimport dari paket java.awt)
void setWarna(Color warnaBaru) {
// Metode untuk mengganti warna
warna = warnaBaru; // ganti nilai variabel instansi
gambar(); // gambar ulang bentuk geometris ini, dengan warna baru
}
void gambar() {
// metode untuk menggambar
? ? ? // perintaha apa yang harus diletakkan di sini?
}
. . . // variabel dan metode instansi lain
} // akhir kelas BentukGeometris
Sekarang metode gambar() mungkin menjadi serba salah. Masalahnya, setiap bentuk digambar dengan cara berbeda. Metode setWarna() dapat digunakan oleh semua bentuk. Lalu bagaimana komputer tahu bagaimana menggambar bentuk tersebut jika metode gambar() dipanggil? Mudahnya, kita bisa jawab dengan : Komputer akan menjalankan perintah gambar() dengan meminta bentuk tersebut untuk menggambar sendiri. Setiap objek bentuk tahu apa yang harus dilakukan untuk menggambar dirinya.
Dalam prakteknya, ini berarti setiap kelas turunan dari kelas BentukGeometris memiliki metode gambar() sendiri-sendiri, yaitu :
class PersegiPanjang extends BentukGeometris {
void gambar() {
. . . // perintah untuk menggambar persegi panjang
}
. . . // metode atau variabel lain
}
class Oval extends BentukGeometris {
void gambar() {
. . . // perintah untuk menggambar oval
}
. . . // metode atau variabel lain
}
class KotakLingkar extends BentukGeometris {
void gambar() {
. . . // perintah untuk menggambar kotak bersudut lingkar
}
. . . // metode atau variabel lain
}
Jika gambarku adalah variabel bertipe BentukGeometri, variabel ini bisa merujuk pada objek dengan bertipe PersegiPanjang, Oval, atau KotakLingkar. Ketika program
Tidak ada komentar:
Posting Komentar