Pemrograman Berorientasi Objek (PBO) merupakan paradigma pemrograman yang fundamental dalam dunia pengembangan perangkat lunak modern. Di kelas 11 semester 2, siswa biasanya diperkenalkan pada konsep-konsep PBO yang lebih mendalam, seperti pewarisan (inheritance), polimorfisme (polymorphism), enkapsulasi (encapsulation), dan abstraksi (abstraction). Memahami konsep-konsep ini secara teori saja tidaklah cukup. Latihan soal yang variatif dan relevan adalah kunci untuk menguasai PBO dan siap menghadapi tantangan di dunia nyata.
Artikel ini akan menyajikan beberapa contoh soal PBO kelas 11 semester 2 yang dirancang untuk menguji dan memperkuat pemahaman siswa terhadap konsep-konsep inti PBO. Setiap soal akan disertai dengan penjelasan mendalam mengenai konsep yang diuji, langkah-langkah penyelesaian, dan bahkan contoh kode program sederhana untuk ilustrasi.
Mengapa latihan soal begitu penting dalam PBO?
Soal:
Buatlah sebuah kelas bernama Buku yang merepresentasikan sebuah buku. Kelas ini harus memiliki atribut judul (String), penulis (String), dan isbn (String). Buatlah juga metode getter dan setter untuk setiap atribut. Kemudian, buatlah sebuah konstruktor yang memungkinkan pembuatan objek Buku dengan nilai awal untuk semua atribut. Terakhir, buatlah sebuah metode tampilkanInfo() yang mencetak informasi lengkap buku ke konsol.
Konsep yang Diuji:
Langkah-langkah Penyelesaian:
Buku: Mulai dengan mendeklarasikan kelas Buku.judul, penulis, dan isbn sebagai private untuk menerapkan enkapsulasi.Buku(String judul, String penulis, String isbn) yang menerima argumen untuk menginisialisasi atribut-atribut tersebut. Gunakan this. untuk membedakan antara parameter konstruktor dan atribut kelas.judul, penulis, isbn), buatlah metode publik yang mengembalikan nilai atribut tersebut (misalnya, public String getJudul()).public void setJudul(String judul)).tampilkanInfo(): Buat metode publik tampilkanInfo() yang akan mencetak nilai dari judul, penulis, dan isbn menggunakan metode getter.Contoh Kode (Java):
public class Buku
private String judul;
private String penulis;
private String isbn;
// Konstruktor
public Buku(String judul, String penulis, String isbn)
this.judul = judul;
this.penulis = penulis;
this.isbn = isbn;
// Getter untuk judul
public String getJudul()
return judul;
// Setter untuk judul
public void setJudul(String judul)
this.judul = judul;
// Getter untuk penulis
public String getPenulis()
return penulis;
// Setter untuk penulis
public void setPenulis(String penulis)
this.penulis = penulis;
// Getter untuk isbn
public String getIsbn()
return isbn;
// Setter untuk isbn
public void setIsbn(String isbn)
this.isbn = isbn;
// Metode untuk menampilkan informasi buku
public void tampilkanInfo()
System.out.println(" " + getJudul());
System.out.println("Penulis: " + getPenulis());
System.out.println("ISBN: " + getIsbn());
public static void main(String args)
// Contoh penggunaan kelas Buku
Buku buku1 = new Buku("Laskar Pelangi", "Andrea Hirata", "978-602-03-0211-5");
buku1.tampilkanInfo();
System.out.println("n--- Mengubah Judul ---");
buku1.setJudul("Sang Pemimpi");
buku1.tampilkanInfo();
Penjelasan Tambahan:
Penggunaan private pada atribut adalah inti dari enkapsulasi. Ini memastikan bahwa data objek tidak dapat diakses atau dimodifikasi secara langsung dari luar kelas, melainkan melalui metode getter dan setter yang telah ditentukan. Hal ini meningkatkan keamanan dan integritas data, serta memungkinkan perubahan implementasi internal tanpa mempengaruhi kode yang menggunakan kelas tersebut.
Soal:
Buatlah sebuah kelas dasar Kendaraan dengan atribut merk (String) dan tahunProduksi (int). Kelas Kendaraan juga memiliki metode tampilkanDetail() yang mencetak merk dan tahun produksi.
Selanjutnya, buatlah dua kelas turunan dari Kendaraan: Mobil dan Motor.
Mobil memiliki atribut tambahan jumlahPintu (int).Motor memiliki atribut tambahan tipeMesin (String).Override metode tampilkanDetail() pada kelas Mobil dan Motor untuk menambahkan informasi spesifik dari masing-masing kelas turunan, namun tetap memanggil metode tampilkanDetail() dari kelas induk untuk mencetak informasi umum.
Konsep yang Diuji:
extends: Penggunaan kata kunci untuk menyatakan hubungan pewarisan.super: Penggunaan kata kunci super untuk memanggil konstruktor atau metode dari kelas induk.Langkah-langkah Penyelesaian:
Kendaraan: Deklarasikan kelas Kendaraan dengan atribut merk dan tahunProduksi, serta konstruktor dan metode tampilkanDetail().Mobil: Deklarasikan Mobil yang extends Kendaraan. Tambahkan atribut jumlahPintu. Buat konstruktor yang memanggil konstruktor kelas induk menggunakan super(). Override metode tampilkanDetail() untuk mencetak informasi mobil dan memanggil super.tampilkanDetail().Motor: Deklarasikan Motor yang extends Kendaraan. Tambahkan atribut tipeMesin. Buat konstruktor yang memanggil konstruktor kelas induk menggunakan super(). Override metode tampilkanDetail() untuk mencetak informasi motor dan memanggil super.tampilkanDetail().main untuk membuat objek Mobil dan Motor, lalu panggil metode tampilkanDetail() mereka.Contoh Kode (Java):
// Kelas Induk
class Kendaraan
protected String merk; // protected agar bisa diakses oleh kelas turunan
protected int tahunProduksi;
public Kendaraan(String merk, int tahunProduksi)
this.merk = merk;
this.tahunProduksi = tahunProduksi;
public void tampilkanDetail()
System.out.println("Merk: " + merk);
System.out.println("Tahun Produksi: " + tahunProduksi);
// Kelas Turunan Mobil
class Mobil extends Kendaraan
private int jumlahPintu;
public Mobil(String merk, int tahunProduksi, int jumlahPintu)
super(merk, tahunProduksi); // Memanggil konstruktor kelas induk
this.jumlahPintu = jumlahPintu;
// Override metode tampilkanDetail
@Override
public void tampilkanDetail()
super.tampilkanDetail(); // Memanggil metode tampilkanDetail dari kelas induk
System.out.println("Jumlah Pintu: " + jumlahPintu);
// Kelas Turunan Motor
class Motor extends Kendaraan
private String tipeMesin;
public Motor(String merk, int tahunProduksi, String tipeMesin)
super(merk, tahunProduksi); // Memanggil konstruktor kelas induk
this.tipeMesin = tipeMesin;
// Override metode tampilkanDetail
@Override
public void tampilkanDetail()
super.tampilkanDetail(); // Memanggil metode tampilkanDetail dari kelas induk
System.out.println("Tipe Mesin: " + tipeMesin);
// Kelas Utama untuk Pengujian
public class MainKendaraan
public static void main(String args)
Mobil sedan = new Mobil("Toyota Avanza", 2022, 4);
Motor sport = new Motor("Honda CBR", 2023, "150cc");
System.out.println("--- Detail Mobil ---");
sedan.tampilkanDetail();
System.out.println("n--- Detail Motor ---");
sport.tampilkanDetail();
Penjelasan Tambahan:
Pewarisan memungkinkan kita untuk membuat kode yang lebih efisien dan terorganisir. Dengan mewarisi dari kelas Kendaraan, kelas Mobil dan Motor tidak perlu mendefinisikan ulang atribut merk dan tahunProduksi atau metode tampilkanDetail() yang umum. Konsep override memungkinkan setiap kelas turunan untuk menyediakan perilaku yang lebih spesifik tanpa kehilangan fungsionalitas dari kelas induk. Penggunaan protected pada atribut kelas induk memberikan fleksibilitas yang cukup untuk kelas turunan.
Soal:
Gunakan kelas-kelas dari Contoh Soal 2 (Kendaraan, Mobil, Motor).
Buatlah sebuah metode dalam kelas utama yang menerima sebuah objek Kendaraan sebagai parameter. Metode ini akan memanggil metode tampilkanDetail() pada objek tersebut.
Kemudian, dalam metode main, buatlah sebuah array yang berisi objek Mobil dan Motor. Iterasi melalui array tersebut dan panggil metode yang telah dibuat sebelumnya untuk setiap elemen array.
Konsep yang Diuji:
Langkah-langkah Penyelesaian:
Kendaraan, Mobil, Motor: Pastikan kelas-kelas ini sudah terdefinisi dengan baik.tampilkanInfoKendaraan: Buat sebuah metode publik statis yang menerima parameter Kendaraan (misalnya, public static void tampilkanInfoKendaraan(Kendaraan k)). Di dalam metode ini, panggil k.tampilkanDetail().main, buat sebuah array Kendaraan (misalnya, Kendaraan daftarKendaraan = new Kendaraan;).Mobil dan Motor. Perhatikan bahwa objek Mobil dan Motor dapat disimpan dalam array bertipe Kendaraan karena adanya upcasting.
daftarKendaraan = new Mobil("Honda Brio", 2021, 4);daftarKendaraan = new Motor("Yamaha Vixion", 2022, "150cc");daftarKendaraan = new Mobil("Suzuki Ertiga", 2020, 4);for-each loop) untuk mengiterasi melalui array daftarKendaraan. Di dalam perulangan, panggil metode tampilkanInfoKendaraan() dengan elemen array sebagai argumen.Contoh Kode (Java):
// (Kelas Kendaraan, Mobil, Motor dari Contoh Soal 2 tetap digunakan di sini)
public class MainPolimorfisme
// Metode yang menunjukkan polimorfisme
public static void tampilkanInfoKendaraan(Kendaraan k)
System.out.println("Memanggil detail kendaraan...");
k.tampilkanDetail(); // Panggilan metode ini akan memanggil implementasi yang sesuai di kelas turunan
System.out.println("----------------------");
public static void main(String args)
// Membuat array objek Kendaraan
// Objek Mobil dan Motor dapat dimasukkan ke dalam array Kendaraan karena upcasting
Kendaraan daftarKendaraan = new Kendaraan;
daftarKendaraan = new Mobil("Toyota Avanza", 2022, 4);
daftarKendaraan = new Motor("Honda CBR", 2023, "150cc");
daftarKendaraan = new Mobil("Honda Brio", 2021, 4);
daftarKendaraan = new Motor("Yamaha NMAX", 2022, "155cc");
System.out.println("--- Menampilkan Detail Semua Kendaraan ---");
// Iterasi melalui array dan memanggil metode tampilkanInfoKendaraan
for (Kendaraan kendaraan : daftarKendaraan)
tampilkanInfoKendaraan(kendaraan);
Penjelasan Tambahan:
Saat k.tampilkanDetail() dipanggil di dalam metode tampilkanInfoKendaraan, Java secara dinamis menentukan metode tampilkanDetail() mana yang harus dijalankan berdasarkan tipe objek sebenarnya yang ada di variabel k saat runtime. Jika k merujuk pada objek Mobil, maka metode tampilkanDetail() dari Mobil akan dijalankan. Jika merujuk pada Motor, maka metode tampilkanDetail() dari Motor yang akan dijalankan. Inilah inti dari polimorfisme runtime. Ini memungkinkan kita menulis kode yang lebih fleksibel dan dapat diperluas.
Soal:
Buatlah sebuah kelas abstrak Bentuk dengan satu metode abstrak hitungLuas() dan satu metode konkret tampilkanNama().
Kemudian, buatlah dua kelas turunan konkret dari Bentuk: Persegi dan Lingkaran.
Persegi memiliki atribut sisi (double) dan mengimplementasikan hitungLuas() untuk menghitung luas persegi.Lingkaran memiliki atribut radius (double) dan mengimplementasikan hitungLuas() untuk menghitung luas lingkaran.Demonstrasikan cara membuat objek dari Persegi dan Lingkaran, lalu panggil metode tampilkanNama() dan hitungLuas() mereka.
Konsep yang Diuji:
Langkah-langkah Penyelesaian:
Bentuk: Gunakan kata kunci abstract untuk mendeklarasikan kelas Bentuk. Deklarasikan metode abstract double hitungLuas(); dan metode konkret public void tampilkanNama() System.out.println("Ini adalah sebuah bentuk."); .Persegi: Deklarasikan Persegi yang extends Bentuk. Tambahkan atribut sisi. Buat konstruktor untuk menginisialisasi sisi. Implementasikan metode hitungLuas() dengan rumus luas persegi (sisi * sisi).Lingkaran: Deklarasikan Lingkaran yang extends Bentuk. Tambahkan atribut radius. Buat konstruktor untuk menginisialisasi radius. Implementasikan metode hitungLuas() dengan rumus luas lingkaran (Math.PI * radius * radius).main, buat objek Persegi dan Lingkaran. Panggil metode tampilkanNama() dan hitungLuas() pada objek-objek tersebut.Contoh Kode (Java):
// Kelas Abstrak
abstract class Bentuk
// Metode abstrak - harus diimplementasikan oleh kelas turunan
public abstract double hitungLuas();
// Metode konkret - bisa langsung digunakan atau di-override
public void tampilkanNama()
System.out.println("Ini adalah sebuah bentuk.");
// Kelas Konkret Persegi
class Persegi extends Bentuk
private double sisi;
public Persegi(double sisi)
this.sisi = sisi;
@Override
public double hitungLuas()
return sisi * sisi;
@Override
public void tampilkanNama()
System.out.println("Ini adalah Persegi.");
// Kelas Konkret Lingkaran
class Lingkaran extends Bentuk
private double radius;
public Lingkaran(double radius)
this.radius = radius;
@Override
public double hitungLuas()
return Math.PI * radius * radius;
@Override
public void tampilkanNama()
System.out.println("Ini adalah Lingkaran.");
// Kelas Utama untuk Pengujian
public class MainAbstraksi
public static void main(String args)
// Tidak bisa membuat objek dari kelas abstrak Bentuk
// Bentuk bentukUmum = new Bentuk(); // Ini akan error
Persegi kotak = new Persegi(5.0);
Lingkaran bola = new Lingkaran(7.0);
System.out.println("--- Detail Persegi ---");
kotak.tampilkanNama();
System.out.println("Luas: " + kotak.hitungLuas());
System.out.println("n--- Detail Lingkaran ---");
bola.tampilkanNama();
System.out.println("Luas: " + bola.hitungLuas());
System.out.println("n--- Menggunakan Polimorfisme dengan Kelas Abstrak ---");
Bentuk daftarBentuk = new Bentuk;
daftarBentuk = kotak;
daftarBentuk = bola;
for (Bentuk b : daftarBentuk)
b.tampilkanNama(); // Akan memanggil implementasi yang sesuai
System.out.println("Luas: " + b.hitungLuas()); // Akan memanggil implementasi yang sesuai
Penjelasan Tambahan:
Kelas abstrak Bentuk mendefinisikan kontrak. Semua kelas yang mewarisi Bentuk harus menyediakan implementasi untuk hitungLuas(). Ini memastikan bahwa setiap objek turunan dari Bentuk memiliki kemampuan untuk menghitung luasnya, meskipun cara perhitungannya berbeda. tampilkanNama() di-override untuk memberikan deskripsi yang lebih spesifik dari masing-masing bentuk. Penggunaan kelas abstrak sangat berguna untuk mendefinisikan kerangka dasar dari sebuah sistem dan memaksa kelas turunan untuk menyediakan detail implementasi.
Menguasai Pemrograman Berorientasi Objek membutuhkan lebih dari sekadar menghafal definisi. Melalui latihan soal yang terstruktur seperti contoh-contoh di atas, siswa dapat secara aktif menerapkan konsep-konsep PBO, memperdalam pemahaman mereka, dan membangun keterampilan pemecahan masalah yang esensial.
Setiap contoh soal dirancang untuk menguji satu atau lebih pilar PBO: enkapsulasi, pewarisan, polimorfisme, dan abstraksi. Dengan membiasakan diri dengan berbagai skenario dan cara penyelesaiannya, siswa akan lebih siap untuk menghadapi tantangan dalam tugas pemrograman, proyek akhir, bahkan dalam studi lanjut di bidang teknologi informasi.
Ingatlah bahwa kunci keberhasilan dalam pemrograman adalah praktik yang konsisten. Teruslah berlatih, bereksperimen dengan kode, dan jangan ragu untuk mencari solusi ketika menghadapi kesulitan. Selamat belajar PBO!