Konsep OOP

Materi Belajar / JavaScript / Konsep OOP

🧩 Konsep Dasar Object-Oriented Programming (OOP) di JavaScript

Object-Oriented Programming atau yang dikenal dengan OOP adalah paradigma pemrograman yang berpusat pada 'objek' daripada 'fungsi' dan 'logika'. Objek ini adalah entitas yang memiliki data (properti) dan perilaku (metode). Menggunakan OOP membantu kita membuat kode yang lebih terstruktur, modular, mudah dipelihara, dan dapat digunakan kembali (reusable).
Meskipun JavaScript pada dasarnya adalah bahasa berbasis prototipe, ES6 memperkenalkan sintaks class yang membuatnya lebih mirip dengan bahasa OOP klasik, memudahkan penerapan konsep-konsep OOP yang akan kita pelajari di sini.

🧱 Pilar Utama OOP

Berikut adalah konsep-konsep kunci dalam OOP yang akan kita bahas:

💻 Contoh Kode OOP:

index.html
<!DOCTYPE html>
<html lang="id">
<head>
  <title>Contoh OOP JavaScript</title>
  <style>
    body { font-family: Arial, sans-serif; margin: 20px; line-height: 1.6; }
    .output { border: 1px solid #ccc; padding: 10px; margin-top: 10px; background-color: #f9f9f9; border-radius: 5px;}
    h2 { color: #333; margin-top: 15px;}
    p { margin: 5px 0; }
    .highlight { color: green; font-weight: bold; }
  </style>
</head>
<body>
  <h1>Demo Konsep OOP di JavaScript</h1>
  <div id="infoOutput" class="output">Hasil akan ditampilkan di sini dan di konsol browser...</div>

  <script>
    const outputDiv = document.getElementById('infoOutput');
    let htmlContent = "";

    // 1. Kelas (Class) dan Objek (Object)
    htmlContent += "<h2>1. Kelas & Objek</h2>";
    class Kendaraan {
      constructor(nama, roda) {
        this.nama = nama;     // Properti publik
        this.roda = roda;     // Properti publik
        let _bahanBakar = 70; // Properti "private" (disimulasikan dengan closure dalam constructor)
                              // Hanya bisa diakses oleh metode dalam Kendaraan

        // Metode untuk mendapatkan bahan bakar (getter)
        this.getBahanBakar = function() {
          return _bahanBakar;
        }
        
        // Metode untuk mengurangi bahan bakar
        this.pakaiBahanBakar = function(jumlah) {
          if (jumlah > 0 && _bahanBakar >= jumlah) {
            _bahanBakar -= jumlah;
            return true;
          }
          return false;
        }
         // Metode untuk menambah bahan bakar
        this.isiBensin = function(jumlah) {
            if(jumlah > 0) {
                 _bahanBakar += jumlah;
                 if (_bahanBakar > 100) _bahanBakar = 100; // Maksimum 100%
                 return true;
            }
            return false;
        }
      }

      // Metode (Method) publik
      info() {
        const infoText = `Kendaraan: ${this.nama}, Roda: ${this.roda}, Bahan Bakar: ${this.getBahanBakar()}%`;
        console.log(infoText);
        htmlContent += `<p>${infoText}</p>`;
      }
    }

    let mobil = new Kendaraan("Mobil Sedan", 4);
    let motor = new Kendaraan("Motor Sport", 2);

    mobil.info(); 
    motor.info();
    
    htmlContent += `<p>Mobil memakai bahan bakar: ${mobil.pakaiBahanBakar(10) ? 'Berhasil' : 'Gagal'}. Bahan bakar sekarang: ${mobil.getBahanBakar()}%</p>`;
    htmlContent += `<p>Motor mengisi bensin: ${motor.isiBensin(20) ? 'Berhasil' : 'Gagal'}. Bahan bakar sekarang: ${motor.getBahanBakar()}%</p>`;
    mobil.info(); // Cek bahan bakar mobil setelah dipakai
    motor.info(); // Cek bahan bakar motor setelah diisi

    // 2. Pewarisan (Inheritance)
    htmlContent += "<h2>2. Pewarisan (Inheritance)</h2>";
    class MobilListrik extends Kendaraan {
      constructor(nama, roda, bateraiKwh) {
        super(nama, roda); // Memanggil constructor kelas induk (Kendaraan)
        this.bateraiKwh = bateraiKwh; // Properti spesifik MobilListrik
        // Karena _bahanBakar dienkapsulasi di Kendaraan, MobilListrik tidak bisa langsung akses.
        // MobilListrik akan memiliki getBahanBakar() dan pakaiBahanBakar() dari Kendaraan.
        // Jika MobilListrik tidak pakai bahan bakar konvensional, ini perlu penyesuaian desain.
        // Untuk demo ini, kita anggap mobil listrik mungkin hybrid atau metode bahan bakar diabaikan.
      }

      // Override metode info
      info() {
        // super.info(); // Bisa panggil implementasi induk jika mau
        const infoIndukText = `Kendaraan: ${this.nama}, Roda: ${this.roda}`; // Akses properti publik dari induk
        const infoListrikText = `${infoIndukText}, Kapasitas Baterai: ${this.bateraiKwh} kWh. Bahan Bakar (dari induk): ${this.getBahanBakar()}%`;
        console.log(infoListrikText);
        htmlContent += `<p class="highlight">${infoListrikText}</p>`;
      }

      chargeBaterai() {
        const chargeText = `${this.nama} sedang mengisi baterai...`;
        console.log(chargeText);
        htmlContent += `<p>${chargeText}</p>`;
      }
    }

    let tesla = new MobilListrik("Tesla Model Y", 4, 75);
    tesla.info(); // Akan memanggil info() dari MobilListrik
    tesla.chargeBaterai();
    tesla.pakaiBahanBakar(5); // Metode dari parent tetap bisa dipanggil
    tesla.info(); // Lihat efek bahan bakar (jika relevan untuk hybrid)


    // 3. Enkapsulasi (Contoh dengan _bahanBakar dan metode get/set/pakai)
    htmlContent += "<h2>3. Enkapsulasi</h2>";
    htmlContent += "<p>Properti _bahanBakar di kelas Kendaraan dienkapsulasi. Akses dan modifikasi dilakukan melalui metode seperti getBahanBakar(), pakaiBahanBakar(), dan isiBensin().</p>";
    // console.log(mobil._bahanBakar); // Ini akan undefined karena _bahanBakar ada dalam scope constructor (closure)

    // 4. Polimorfisme (Contoh dengan method overriding 'info')
    htmlContent += "<h2>4. Polimorfisme</h2>";
    htmlContent += "<p>Metode info() pada Kendaraan dan MobilListrik adalah contoh polimorfisme. Objek mobil (instance Kendaraan) dan tesla (instance MobilListrik) keduanya memiliki metode info(), tapi perilakunya berbeda sesuai implementasi di kelasnya masing-masing.</p>";
    
    outputDiv.innerHTML = htmlContent;
  </script>
</body>
</html>

⚙️ Demo Interaktif: Definisikan Kelas Sendiri

Cobalah untuk membuat objek hewan peliharaan sendiri dengan mengubah nilai di bawah ini dan lihat bagaimana objek dibuat berdasarkan kelas Peliharaan.

💡 Tips: Gunakan sintaks class ES6 untuk OOP di JavaScript modern karena lebih bersih dan mirip bahasa OOP lain. Namun, jangan lupakan bahwa di baliknya, JavaScript tetap menggunakan pewarisan berbasis prototipe (prototypal inheritance). Memahami prototipe akan memberi Anda pemahaman yang lebih dalam tentang cara kerja objek di JavaScript.

Ikuti Tantangan