Hingga Chapter terakhir Section sebelumnya, kita menulis kode yang memisahkan data (variabel) dari perilaku (method) yang mengolah data tersebut. Pendekatan itu natural untuk program kecil, tetapi ketika program membesar — puluhan data yang saling berkaitan dan ratusan baris kode yang menyentuh data yang sama — menjadi sulit menjaga data tetap konsisten. Object-Oriented Programming (OOP) menjawab masalah tersebut dengan menggabungkan data dan perilaku ke dalam satu unit bernama object. Java dirancang sebagai bahasa OOP sejak awal, sehingga memahami cara berpikir OOP adalah prasyarat membaca hampir semua kode Java di dunia nyata. Pada Section ini kita membangun pemahaman OOP bertahap, dimulai dari filosofi dan empat pilar utamanya.
Dari Prosedural ke Berorientasi Objek #
Dalam gaya prosedural, kita menyimpan data di satu tempat lalu mengolahnya dari tempat lain. Data buku perpustakaan bisa hidup sebagai variabel-variabel lepas — judul1, penulis1, tahunTerbit1 — lalu method terpisah mencetak atau memvalidasinya. Setiap buku baru menuntut satu set variabel baru, dan setiap perubahan bentuk data harus disuntikkan ke banyak tempat; duplikasi semacam ini adalah sumber galat yang sulit dilacak.
OOP membalik pola pikirnya: kita mendefinisikan sekali sebuah class yang menjelaskan struktur data beserta perilakunya, lalu mencetak object sebanyak yang dibutuhkan dari class tersebut. Sebuah object membawa datanya sendiri — object buku pertama tidak memengaruhi isi object buku kedua — dan hanya bisa diubah melalui method yang class sediakan. Dengan demikian, tanggung jawab atas data jelas tempatnya: di dalam class yang mendefinisikannya.
Java menerapkan OOP secara ketat. Semua kode harus hidup di dalam class, tidak ada fungsi global yang berdiri sendiri, dan setiap class pada akhirnya diturunkan dari class Object milik pustaka standar. Kata kunci seperti class, new, extends, dan private adalah perkakas utama yang akan kita gunakan sepanjang Section ini.
Empat Pilar OOP #
Teori OOP sering diringkas menjadi empat pilar. Tabel berikut memetakan setiap pilar ke pertanyaan praktis yang pilar tersebut jawab, beserta perkakas Java yang menyertainya:
| Pilar | Pertanyaan praktis | Perkakas di Java |
|---|---|---|
| Encapsulation | Bagaimana melindungi data agar tidak diubah sembarangan? | field private, method akses public |
| Inheritance | Bagaimana menggunakan ulang kode yang sudah ada? | extends, super |
| Polymorphism | Bagaimana satu perintah berperilaku berbeda tiap object? | method overriding, dynamic dispatch |
| Abstraction | Bagaimana menyembunyikan kerumitan di balik nama yang sederhana? | abstract class, interface |
Encapsulation menyembunyikan data internal object di balik method. Data saldo rekening bank, misalnya, tidak boleh dikurangi langsung dari luar object; perubahan harus melewati method tarik() yang memeriksa syaratnya. Invarian seperti “saldo tidak pernah negatif” menjadi tanggung jawab satu tempat, bukan harapan pada kebaikan seluruh kode pemanggil.
Inheritance memungkinkan class baru mewarisi field dan method class lama, lalu menambah atau mengubah bagian yang berbeda. Class BukuFiksi mewarisi kemampuan dasar Buku, lalu menambahkan field genre. Kode dasar ditulis sekali dan dipakai berulang.
Polymorphism membuat satu panggilan method menghasilkan perilaku berbeda tergantung object nyata yang ditunjuk variabel. Kode pengolah daftar buku cukup memanggil deskripsi(); JVM yang memilih versi BukuFiksi atau BukuReferensi saat runtime.
Abstraction menyediakan nama sederhana untuk operasi tanpa membebankan detail pelaksanaannya. Method deskripsi() sendiri adalah abstraksi kecil: pemanggil tahu apa yang didapatkan tanpa perlu tahu bagaimana teksnya dirangkai. Bentuk formalnya — abstract class dan interface — dibahas pada Chapter khusus di akhir Section ini.
Empat Pilar dalam Satu Program #
Mari kita lihat keempat pilar bekerja bersama dalam satu program perpustakaan mini. Program berikut mendefinisikan class Buku dengan data terlindungi, class BukuDigital yang mewarisinya, lalu memanggil method yang perilakunya ditentukan saat runtime:
public class ContohEmpatPilar {
public static void main(String[] args) {
Buku favorit = new BukuDigital("Laut Bercerita", "Leila S. Chudori", 380);
System.out.println(favorit.deskripsi());
favorit.catatPeminjaman();
System.out.println("Judul: " + favorit.getJudul());
}
}
class Buku {
private String judul;
private String penulis;
private int jumlahPinjam;
Buku(String judul, String penulis) {
this.judul = judul;
this.penulis = penulis;
}
String deskripsi() {
return "Buku cetak: " + judul + " oleh " + penulis;
}
String getJudul() {
return judul;
}
void catatPeminjaman() {
jumlahPinjam = jumlahPinjam + 1;
System.out.println("Peminjaman ke-" + jumlahPinjam + " untuk " + judul);
}
}
class BukuDigital extends Buku {
private int jumlahHalaman;
BukuDigital(String judul, String penulis, int jumlahHalaman) {
super(judul, penulis);
this.jumlahHalaman = jumlahHalaman;
}
@Override
String deskripsi() {
return "Buku digital: " + getJudul() + ", " + jumlahHalaman + " halaman";
}
}Output yang Dihasilkan:
Buku digital: Laut Bercerita, 380 halaman
Peminjaman ke-1 untuk Laut Bercerita
Judul: Laut BerceritaBeberapa kata kunci pada program di atas belum kita bedah tuntas, dan itu memang disengaja — masing-masing memiliki Chapter sendiri. Untuk sekarang, mari kita amati peta besarnya:
- Baris 4 (
Buku favorit = new BukuDigital(...)): variabel bertipeBukumenunjuk object buatan classBukuDigital. Perintahnewmenciptakan object baru di memori; tipe variabel boleh berupa parent dari tipe object nyatanya (pilar polymorphism). - Baris 6 (
favorit.deskripsi()): meskipun variabel bertipeBuku, method yang dijalankan adalah versi milikBukuDigitalkarena JVM memeriksa object nyata saat runtime, bukan tipe variabelnya. - Baris 12-14 (
private String judul; ...): fieldBukuditandaiprivatesehingga kode luar tidak bisa membaca atau menulisjudulsecara langsung; satu-satunya pintu masuk adalah method sepertigetJudul()(pilar encapsulation). - Baris 25 (
class BukuDigital extends Buku):extendsmenyatakan bahwaBukuDigitalmewarisi seluruh field dan methodBuku, lalu menambahkan fieldjumlahHalamanmiliknya sendiri (pilar inheritance). - Baris 39 (
String deskripsi()): penanda@Overridemenegaskan bahwa method ini menggantikan versi parent — anotasi ini akan kita bedah pada Chapter Method Overriding. - Baris 8 (
favorit.catatPeminjaman()): method warisanBukutersedia pada objectBukuDigitaltanpa ditulis ulang — bukti pewarisan memindahkan perilaku secara otomatis.
Empat pilar tersebut bukan sekadar kosakata ujian sertifikasi — pilar adalah alat pengendali kompleksitas. Encapsulation membatasi ruang tempat data bisa rusak, inheritance memangkas duplikasi, polymorphism memungkinkan kode generis, dan abstraction menjaga pemanggil berpikir pada level masalah. Langkah konkret pertama kita adalah membedah dua kata paling mendasar dari semuanya: class sebagai cetak biru dan object sebagai wujud nyatanya — pokok bahasan Chapter berikutnya.
Referensi #
- Oracle: dev.java — Object-Oriented Programming
- Java Language Specification — Chapter 8: Classes
- API java.base — java.lang.Object
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
ContohEmpatPilar.java
Unduh berkaspublic class ContohEmpatPilar {
public static void main(String[] args) {
Buku favorit = new BukuDigital("Laut Bercerita", "Leila S. Chudori", 380);
System.out.println(favorit.deskripsi());
favorit.catatPeminjaman();
System.out.println("Judul: " + favorit.getJudul());
}
}
class Buku {
private String judul;
private String penulis;
private int jumlahPinjam;
Buku(String judul, String penulis) {
this.judul = judul;
this.penulis = penulis;
}
String deskripsi() {
return "Buku cetak: " + judul + " oleh " + penulis;
}
String getJudul() {
return judul;
}
void catatPeminjaman() {
jumlahPinjam = jumlahPinjam + 1;
System.out.println("Peminjaman ke-" + jumlahPinjam + " untuk " + judul);
}
}
class BukuDigital extends Buku {
private int jumlahHalaman;
BukuDigital(String judul, String penulis, int jumlahHalaman) {
super(judul, penulis);
this.jumlahHalaman = jumlahHalaman;
}
@Override
String deskripsi() {
return "Buku digital: " + getJudul() + ", " + jumlahHalaman + " halaman";
}
}