Konsep Kelas dan Obyek dalam Java
1 Maret 1999
public class HelloWorldApplet extends Applet{
public void
paint (graphics g) {
g.drawString("Hello World!", 50, 25);
}
}
Setiap applet di-refer dalam HTML dengan sintaks (bagian bergaris bawah menunjukkan harga-harga yang harus diberikan):
Peragaan saat di-browse, misalnya dengan appletviewer dengan perintah:
Kelas lingkaran tersebut dalam bahasa Java didefinisikan sbb.
// method
yang menghitung kel.& luas
public
double keliling() {
return 2*3.14159*r;
}
public
double luas() {
return 3.14159*r*r;
}
}
Sebagai instance dari kelasnya, obyek merupakan sesuatu yang perlu
di-refer eksistensinya dengan suatu variabel (kita sebut bvariabel
referensi).
Note: dalam pemrograman non object-oriented (misalnya C) maka luas lingkaran c dihitung oleh prosedur misalnya luas()dan variabel c menjadi argument dalam penghitungannya sbb.
b = fungsiX(a)
// method
constructor
public
Lingkaran(double x,double y,double r) {
this.x = x; this.y = y; this.r = r;
// Keyword this untuk mengakses variabel
// obyek ybs.; bisa dihilangkan jika nama
// variabel sudah jelas berbeda
}
....
// method
yang menghitung kel.&luas
....
Konstruktor dapat dispesifikasikan dalam lebih dari satu cara pemanggilan
yang berbeda. Contohnya dalam kelas Lingkaran di atas selain (1) dengan
tiga bilangan (x, y, t), didefinisikan juga konstruktor (2) dengan hanya
harga r, (3) dengan harga yang dimiliki obyek lingkaran lain, dan (3) tanpa
harga argumennya.
// dari
obyek lingkaran lain
public
Lingkaran(Lingkaran c) {
x = c.x; y = c.y; r = c.r;
}
// harga
r saja
public
Lingkaran (double r) {
x = 0; y = 0; this.r = r;
}
// tanpa
argument
public
Lingkaran () {x = 0; y = 0; r = 0;}
....
}
public Lingkaran(Lingkaran
c) {this(c.x, c.y, c.r);}
public
Lingkaran (double r) {this(0, 0, r);}
public
Lingkaran () {this(0, 0, 0);}
....
}
Bagaima Java melakukannya? Java akan mengenalinya berdasarkan jumlah
& ragam dari argumen! Jadi jangan membuat dua konstruktor dengan jumlah
dan jenis argumen yang sama.
Bukan hanya konstruktor, setiap metoda dapat dispesifikasikan dalam beberapa cara yang berbeda (di-overload) metoda melakukan fungsi yang sama berdasarkan argumen yang berbeda Java akan mengenalinya dari jumlah dan ragam argumen seperti di atas. Pendefinisian metoda demikian disebut method overloading.
Metoda Kelas (disebut juga Static Method) adalah metoda yang dimiliki oleh kelas tanpa memperhatikan ada/tidaknya obyek dari kelas tersebut. Biasanya untuk fungsi-fungsi library. Metoda kelas diakses melalui nama kelasnya bukan dari obyeknya. Contohnya pemanggilan Math.sqrt() dalam coding berikut ini adalah memanggil mtoda sqrt() dalam kelas Math.
Note: Kelas Math merupakan library yang berisikan banyak metoda penghitungan matematika.
Selain dengan konstruktor variabel obyek dapat dapat diinisialisasi
dengan assignment pada bagian deklarasinya:
Sementara untuk menginisialisasi suatu Variabel Kelas kita tidak
bisa menggunakan konstruktor tapi dapat dilakukan dengan
static initializer.
Static initializer dijalankan saat kelas pertama kali diakses/di-load.
Deklarasi
Static
initializer tidak perlu nama, argumen, dan
return value.
Contoh
Static
Initializer
Untuk obyek yang mengalokasi resource lain, penghapusan dinyatakan
oleh metoda finalizer baru kemudian Java melakukan garbage collection.
Contoh
resource:
file descriptor, socket. Note: finalizer adalah metoda obyek
tanpa argumen.
"Pewarisan" sifat ini dilakukan dengan class extention (notasi
extends)
Contoh TANPA Inheritance. Didefinisikan suatu kelas LingkaranGrafis yang meniru sifat-sifat Lingkaran dengan membuat obyek Lingkaran di dalamnya di tambah beberapa sifat baru.
Contoh: DENGAN Inheritance.
Kelas Final (Final Class) adalah kelas yang tidak dapat di-inherit
lagi (dpl. tidak dapat dibuat subclass-nya). Deklarasi kelas final
adalah dengan menambahkan keyword final
sebelum nama kelasnya.Tujuan dengan spesifikasi ini agar compiler
dapat mengoptimasikan pemanggilan kelas.
Setiap kelas selalu memiliki superclass-nya kecuali kelas Object yang merupakan superclass dari setiap kelas dalam Java (termasuk Java API). Metoda-metoda kelas Object dapat dipanggil oleh setiap obyek Java. Jika suatu kelas tidak didefinisikan dengan extends maka kelas tersebut memiliki superclass langsung Object.
Suatu kelas dapat memanfaatkan konstruktor dari super class-nya dengan prefiks keyword super (mengganti nama superclass).
Pemanggilan konstruktor superclass tersebut dibatasi untuk hanya dilakukan dalam konstruktor class ybs. dan harus muncul sebagai statement pertama (setelah tanda { ). Pemanggilan tsb. bahkan diperlukan jika data yang diakses bersifat private (akan dibicarakan nanti).Secara default saat suatu obyek diciptakan, Java akan menjalankan konstruktor-nya, serta konstruktor dari setiap superclass-nya.Urutannya adalah mulai dari konstruktor kelas obyek paling atas (Object) ke kelas obyek ybs.
Contoh: Saat obyek LingkaranGrafis diciptakan, Java menjalankan konstr. Object, lalu konstr. Lingkaran, dan baru kemudian konstr. LingkaranGrafis.Apabila dalam kelas obyek tsb. tidak mendefinisikan konstruktor maka Java akan membuatkan konstruktor default-nya yang bersifat public. Jika pada LingkaranGrafis tidak ada konstr. maka seolah-olah Java menambahkan baris:public LingkaranGrafis() { super(); }Note: Tetapi jika superclass-nya juga tidak memiliki konstruktor maka akan terjadi compiler error!Jika konstruktor didefinisikan dengan
Jika tidak mau bersifat public, maka hindari konstr. default dengan mendefinisikanya!
- keyword public: semua kelas lain bisa mengaksesnya
- keyword protected: hanya subclass-nya yang bisa mengaksesnya
- keyword private: tidak ada kelas lain yang bisa mengaksesnya
Apakah juga hal yang terjadi pada konstruktor, terjadi pula pada finalizer? TIDAK! Apabila obyek dari suatu kelas hendak di hapuskan dengan memanggil finalizer-nya, dan jika superclass-nya juga memiliki finalizer, maka finalizer superclass ini pun harus dipanggil juga membentuk rantai perintah finalizer.
Jika terdefinisi suatu variabel dalam suatu kelas yang bernama sama dengan variabel. yang ada dalam superclass-nya, bagaimanakah hubungannya? Keduanya berbeda! Variabel tersebut disebut shadowed variable. Untuk dapat membedakannya maka perlu diberikan identitas "pemiliknya", yaitu miliknya dengan referensi keyword this (misalnya variable x,ditulis this.x) dan milik superclass dengan referensi keyword super (misalnya variable x,ditulis super.x) atau dengan cara casting (Misalnya nama kelas superclassnya adalah Y, casting ditulis((Y) this).x).
Contoh: Jika C subclass dari B, Bsubclass dari A, x adalah var. shadowed var. x di B, dan juga var. x di A
// semua code ini dalam metoda di kelas CDalam hal metoda, jika mendefinisikan ulang suatu metoda yang muncul di superclass di dalamkelasybs. maka yang terjadi adalah overriding. Perbedaannya adalah bahwa yang berlaku adalah metoda kelas dari obyek tersebut (walaupun melalui casting!).
x // variabel x dalam kelas C
this.x // variabel x dalam kelas C
super.x // variabel x dalam kelas B
((B) this).x // variabel x dalam kelas B
((A) this).x // variabel x dalam kelas A
// super.super.x tidak boleh digunakanContoh: jika dibentuk subclass Elips dari Lingkaran maka metoda luas dan keliling dari Lingkaran perlu di-overrriding sesuai dengan sifat kelas ElipsJika suatu etoda mendapat prefiks keyword final, maka metoda tersebut tidak dapat di-overriden (note: demikian halnya metoda static dan private tidak bisa di-overriden, mengapa?)Jika kita menganggap bahwa suatu metoda tidak akan dioverrid lagi maka kita perlu mendefinisikannya final guna memungkinkan compiler melakukan optimisasi. Penjelasannya adalah berkaitan dengan mekanisme Dynamic Method Lookup (DML) yang dilakukan Java sebagai berikut.
Karena adanya metoda/variabel yang bisa ter-overriden dalam suatu "keluarga" (kelas + semua subclass-nya) maka interpreter-lah yang bertugas mengidentifikasi metoda yang sebenarnya (bukan compiler!) pada saat run dengan DML. Sementara suatu akses pada metoda final dilakukan secara langsung, akses metoda biasa yang dilakukan melalui DML pasti menjadi lebih lambat .
Method overriding dan variable shadowing berbeda secara konseptual, namun sintaks Java untuk memanggilnya sama. Yaitu menggunakan keyword super.
class A {
int i = 1;
int f() { return i;}
}class B extends A {
int i;
int f() { i = super.i + 1; return super.f() + i;}
}Sebelumnya sudah disinggung bahwa metoda finalize superclass tidak otomatis dipanggil seperti halnya pada konstruktor, jadi perlu terjadi rantai rinalizer. Namun tidak dijelaskan mengapa itu perlu dilakukan. Pendefinisian metoda finalize dalam suatu kelas di mana dalam superclass-nya sudah terdefinisi metoda finalize juga maka terjadi overriding metoda tsb.
Finalizer milik superclass harus dipanggil di baris terakhir dari metoda finalizer tsb.:
super.finalize()
Penyembunyian Data & Encapsulation
Penyembunyain data dilakukan untuk menyembunyikan rincian implementasi internal dengan tujuan:Data atau metoda dapat diakses atau tersembunyi dengan mendeklarasikan ragam data atau metoda tersebut dengan keyword-keyword sbb.:
- melindungi kelas terhadap kesalahan yang tak disengaja atau memang disengaja
- modularitas pengembangan perangkat lunak
- penulisan program yang elegance
- memudahkan dokumentasi
- public: Setiap metoda kelas apa saja dan dalam package mana saja dapat mengaksesnya
- private: Hanya metoda di dalam kelas yang sama yang bisa mengaksesnya
- protected: Dapat diakses dari semua metoda di dalam subclass-nya serta kelas-kelas dalam package yang sama
- package: Metoda-metoda di dalam kelas-kelas dengan package yang sama dapat mengaksesnya
Sebaiknya ragam public digunakan untuk metoda-metoda dan konstanta-konstanta yang bagian dari API publik dari kelas. Data yang paling penting atau paling sering digunakan boleh dinyatakan public (tapi biasanya itu di-non- public-kan & dienkapsulasi dalan metoda akses yang public).Ragam private digunakan untuk data yang sangat terkait untuk kepentingan metoda di dalam kelas itu saja. Package: kelompok kelas yang ditempatkan dalam satu berkas; idealnya kelas-kelas dalam satu package berelasi dan kooperatif satu dengan lainnya
Ringkasan Visibilitas
Visibilitas untuk public protected package private Kelas yang sama ya ya ya ya Kelas dalam package yang sama untuk ya ya ya tidak Subclass dalam package yang berbeda ya ya tidak tidak Bukan subclass dan berada dl package lain ya tidak tidak tidak Contoh Kasus: dari kelas Lingkaran sebelumnya (x,y,r) visibel untuk subclass/kelas kooperatif karena secara logis subclass bisa perlu mengaksesnya langsung. Bagi kelas obyek lain secara umum maka perlu disediakan metoda public yang dapat memodifikasinya variabel-variabel tersebut sambil dapat mevalidasi harganya.
Contoh Metoda-metoda Akses
package shapes;
public class Lingkaran {
protected double x,y;
protected double r;private static final double MAXR = 100.0;
private boolean cekjarijari(double r) {
return (r <= MAXR); }public Lingkaran(double x, double y,
double r) {
this.x = x; this.y =y;
if (cekjarijari(r)) this.r = r;
else this.r = MAXR;
}public Lingkaran(double r) {
this(0.0, 0.0, r); }
public Lingkaran() {
this(0.0, 0.0, 0.0); }
public void moveto(double x, double y) {
this.x = x; this.y = y; }
public void move(double dx, double dy) {
x += dx; y += dy; }
public void setRadius(double r){
this.r = (cekjarijari(r))?r:MAXR; }
public final double getX() {
return x;}
public final double getY() {
return y;}
public final double getRadius() {
return r;}
}
Kelas Abstraks dan Interface
Kelas abstraks maupun interface digunakan untuk mendefinisikan suatu kelas secara umum dimana kelak akan dibentuk sejumlah subclass yang melakukan metoda dengan cara yang berbeda (walaupun namanya sama!). Jadi kelas abstraks digunakan untuk men-generalisasi sejumlah kelas yang sifatnya mirip namun implementasinya berbeda.Di dalam definisinya kelas abstraks maupun interface hanya berisikan nama-nama metoda tsb. oleh karena itu kelas abstraks tidak dapat diinstansiasi (diciptakan obyeknya) tapi instans dari subclass-nya (untuk kelas abstraks) atau kelas implementasinya (untuk antarmuka) dapat diperlakukan sebagai instans-nya.
Mengingat hanya bisa satu superclass yang diekstend dalam suatu kelas (ini khusus dalam bahasa Java) maka interface digunakan untuk mengakomodasikan "multiple inheritance" mendampingi superclass.
Berikut ini beberapa perbedaan kelas abstraks dengan interface.
Kelas Abstraks didefinisikan untuk hanya berisi sejumlah memiliki metoda abstraks (Metoda abstraks didefinisikan: metoda yang dideklarasikan dengan keyword abstract serta tanpa implementasi). Subclass dari suatu kelas abstraks adalah juga kelas abstraks apabila metoda abstraks-nya tidak diimplementasikan (jadi hanya di-inherit dan ditambah metoda-metoda abstraks lainnya). Variabel referensi suatu kelas abstraks dapat digunakan untuk merefer obyek dari kelas turunannya.
- Deklarasi: interface menggunakan keyword interface sedangkan kelas abstraks menggunakan keyword abstract
- Sintaks: Kelas abstraks "di-inherit" (dgn. keyword extends) sedangan interface "diimplementasikan" (dgn. keyword implements)
- Inheritance/implementasi: Kelas abstraks adalah kelas dan sebagai superclass hanya boleh single inheritance, sementara interface bukan kelas, jadi bisa multiple interface
Contoh Pendefinisian Kelas Abstraks
Kelas-kelas yang mirip adalah Bujursangkar, Persegipanjang, Lingkaran, Ellips, Segitiga dan sifat-sifat yang mirip: memiliki luas, dan keliling, namun implementasi masing-masing berbeda. Maka, kelas abstraks akan didefinisikan: kelas Bentuk.Contoh Subclass dari Kelas Abstrakspublic abstract class Bentuk {
public abstract double luas();
public abstract double keliling();
}public class Lingkaran extends Bentuk {
....
public double luas(){ return PI*r*r; }
public double keliling(){return 2*PI*r; }
}public class Bujursangkar extends Bentuk {
....
public double luas(){ return s*s; }
public double keliling(){return 4*s; }
}public class Persegipanjang extends Bentuk {
....
}public class Ellips extends Bentuk {
....
}public class Segitiga extends Bentuk {
....
}
Contoh Obyek Kelas AbstraksObyek-obyek turunan Bentuk bisa mengambil sifat dari subclass-subclass tersebut:
Bentuk [] B = new Bentuk[3];Interface didefinisikan dengan sejumlah nama metoda yang kelak harus dirinci oleh kelas obyek yang didefinisikan mengimplementasikannya. Suatu kelas dapat mengimplementasikan kebih dari satu inteface dan hal ini memungkinkan multiple inheritance. Karena bukan kelas jelas interface tidak bisa diinstansiasi tetapi suatu didefinisikan suatu variabel referensi dari interface tsb. dan variabel ini dapat digunakan untuk merefer obyek dari kelas yang mengimplementasikannya..
B[0] = new Lingkaran(2.0);
B[1] = new BujurSangkar(1.0);
B[2] = new SegiEmpat(4.0, 2.0);
double total_luas = 0;
for (int i; i < B.length; i++) {
total_luas += B[i].luas();
}Dalam antarmuka selain didefinisikan metoda-metoda kosong (belum diimplementasi), dapat juga didefinisikan konstanta yaitu sebagai static var. dan final var. yang apabila diakses perlu dengan prefiks nama antarmukanya di depan konstanta tsb. (mirip variabel kelas).
Seperti halnya subclass, sub-antarmuka dapat juga diturunkan dari suatu antarmuka dengan penambahan metoda abstraks & konstanta lain.
Contoh Antarmuka
Dari contoh kelas abstraks akan dibuat subclass yang meng-inherit sifat luas & keliling dari masing-masing kelas: GbrlLingkaran, GbrBujurSangkar, GbrPersegiPanjang, GbrSegiTiga, dan GbrEllips. Pada kelas-kelas baru tsb. terdapat metoda-metoda-metoda lainnya yang mirip: setWarna, setPosisi, gambarkan. Dibuat antarmuka Gambar untuk ketiga metoda tsb.Implementasinya dalam Gambarlingkaranpublic interface Gambar {
public void setWarna(Color c);
public void setPosisi(double x, double y);
public void gambarkan(DrawWindow dw);
}public class Gambarlingkaran extends
Lingkaran implements Gambar {
....public GbrLingkaran(double x, double y,
double c) { super(x,y,r); }
....
Public void setWarna(color c) {
this.c = c; }public void setPosisi(double x, double c) {
this.x = x; this.y = y; }public void gambarkan(DrawWindow dw) {
dw.drawCircle(x, y, r, c); }
}
Pada implementasi berganda (lebih dari satu interface yang akan diimplementasikan) maka nama-nama Interface ditulis setelah keyword implementsdan dipisahkan dengan koma.Contoh:
Dibentuk kelas baru yang memiliki sifat Skala (Skala sebagai antarmuka)
public class SkalaGbrLingkaran extends GbrLingkaran implements Gambar, Skala {
....
}
Contoh Obyek dari Kelas Abstraks & Antarmuka
Bentuk[] b = new Bentuk[3];
Gambar[] g = new Gambar[3];GbrLingkaran gli = new GbrLingkaran(0,0,5);
GbrSegiEmpat gse = new GbrSegiEmpat(10,20);
GbrBujurSangkar gbs = new GbrBujurSangkar(15);
b[0] = gli; g[0] = gli;
b[1] = gse; g[1] = gse;
b[2] = gbs; g[2] = gbs;
double luas_total = 0;
for (int i; i< b.length; i++){
luas_total += b[i].luas;
g[i].gambarkan(draw_window);
}