Interface & Abstract Class

Di halaman OOP Dasar, kamu sudah belajar Class, Object, dan Inheritance. Sekarang kita naik level — belajar dua konsep yang sangat sering dipakai di Laravel: Interface dan Abstract Class.

Keduanya adalah cara untuk membuat kontrak yang memaksa class lain mengikuti aturan tertentu.

1. Interface — Kontrak yang Harus Dipenuhi

Interface adalah "perjanjian" yang mengatakan: "Semua class yang implements saya HARUS punya method-method ini."

Analogi

Bayangkan sebuah stopkontak listrik. Semua alat elektronik (TV, laptop, kipas) harus punya colokan yang cocok. Stopkontak tidak peduli merek alatnya — yang penting coklokannya sesuai.

<?php
declare(strict_types=1);

// Interface = Kontrak / Stopkontak
interface PembayaranInterface
{
    public function bayar(int $jumlah): bool;
    public function cekStatus(string $transaksiId): string;
}

:::warning Aturan Interface

  • Interface hanya berisi deklarasi method (tanpa isi/body)
  • Semua method di interface otomatis public
  • Tidak boleh ada property
  • Satu class bisa implements banyak interface :::

Implementasi

<?php
declare(strict_types=1);

// Class yang "menandatangani kontrak"
class PembayaranBankTransfer implements PembayaranInterface
{
    public function bayar(int $jumlah): bool
    {
        // Logika transfer bank
        echo "Transfer bank Rp " . number_format($jumlah) . "\n";
        return true;
    }

    public function cekStatus(string $transaksiId): string
    {
        return "Transfer {$transaksiId}: SUKSES";
    }
}

class PembayaranEWallet implements PembayaranInterface
{
    public function bayar(int $jumlah): bool
    {
        // Logika e-wallet
        echo "Bayar via e-wallet Rp " . number_format($jumlah) . "\n";
        return true;
    }

    public function cekStatus(string $transaksiId): string
    {
        return "E-Wallet {$transaksiId}: PENDING";
    }
}

Keuntungan: Type Hinting

Dengan interface, kamu bisa bikin function yang menerima pembayaran apapun:

<?php

// Tidak peduli Bank Transfer atau E-Wallet — yang penting implements PembayaranInterface
function prosesCheckout(PembayaranInterface $gateway, int $total): void
{
    if ($gateway->bayar($total)) {
        echo "✅ Checkout berhasil!\n";
    }
}

// Kedua class bisa masuk karena sama-sama implements PembayaranInterface
prosesCheckout(new PembayaranBankTransfer(), 150000);
prosesCheckout(new PembayaranEWallet(), 75000);

:::tip Di Laravel Nanti... Laravel sangat banyak menggunakan interface. Contoh:

  • Authenticatable — interface yang harus dipenuhi model User
  • ShouldQueue — interface untuk job yang masuk antrian
  • Renderable — interface untuk object yang bisa di-render ke HTML :::

2. Abstract Class — Template yang Belum Lengkap

Abstract class adalah class yang tidak bisa diinstansiasi langsung — dia hanya berfungsi sebagai template/kerangka untuk class turunannya.

Analogi

Bayangkan sebuah resep masakan dasar. Ada langkah-langkah umum (panaskan minyak, siapkan piring) yang selalu sama, tapi ada langkah yang berbeda tergantung masakannya (bumbu, bahan utama). Resep dasar itu adalah abstract class.

<?php
declare(strict_types=1);

abstract class Hewan
{
    // Property biasa — abstract class BOLEH punya property
    protected string $nama;

    public function __construct(string $nama)
    {
        $this->nama = $nama;
    }

    // Method biasa (sudah ada implementasinya)
    public function tidur(): string
    {
        return "{$this->nama} sedang tidur... 💤";
    }

    // Abstract method — HARUS diimplementasikan oleh class anak
    abstract public function bersuara(): string;
    abstract public function bergerak(): string;
}

Implementasi

<?php

class Kucing extends Hewan
{
    public function bersuara(): string
    {
        return "{$this->nama}: Meong! 🐱";
    }

    public function bergerak(): string
    {
        return "{$this->nama} berjalan dengan anggun";
    }
}

class Burung extends Hewan
{
    public function bersuara(): string
    {
        return "{$this->nama}: Cuit cuit! 🐦";
    }

    public function bergerak(): string
    {
        return "{$this->nama} terbang tinggi di langit";
    }
}

// ❌ TIDAK BISA: $hewan = new Hewan("Test"); — Error!
// ✅ BISA: Class turunan yang sudah lengkap
$kucing = new Kucing("Kitty");
echo $kucing->bersuara();   // Kitty: Meong! 🐱
echo $kucing->tidur();      // Kitty sedang tidur... 💤 (dari parent)

3. Interface vs Abstract — Kapan Pakai Yang Mana?

AspekInterfaceAbstract Class
Keywordimplementsextends
Property❌ Tidak boleh✅ Boleh
Method body❌ Hanya deklarasi✅ Boleh ada implementasi
Multiple✅ Bisa implements banyak❌ Hanya extends satu
Kapan pakai?Kontrak behaviorTemplate dengan logika shared

Aturan Praktis

"Apa yang BISA dilakukan objek ini?" → Interface
"Objek ini ADALAH jenis apa?"        → Abstract Class

Contoh nyata:

<?php

// Interface: Definisikan KEMAMPUAN
interface Searchable
{
    public function search(string $keyword): array;
}

interface Exportable
{
    public function toCSV(): string;
    public function toPDF(): string;
}

// Abstract Class: Definisikan JENIS + logika shared
abstract class BaseModel
{
    protected string $table;

    public function find(int $id): array
    {
        // Logika shared: semua model perlu find()
        return ["id" => $id, "table" => $this->table];
    }

    abstract public function validate(array $data): bool;
}

// Class konkret: gabungkan semuanya
class Product extends BaseModel implements Searchable, Exportable
{
    protected string $table = 'products';

    public function validate(array $data): bool
    {
        return isset($data['name']) && isset($data['price']);
    }

    public function search(string $keyword): array
    {
        return ["Hasil pencarian produk: {$keyword}"];
    }

    public function toCSV(): string
    {
        return "id,name,price\n1,Widget,10000";
    }

    public function toPDF(): string
    {
        return "[PDF] Daftar Produk";
    }
}

Latihan

  1. Buat interface NotifikasiInterface dengan method kirim(string $pesan): bool
  2. Buat 2 class yang implements interface tersebut: NotifEmail dan NotifSMS
  3. Buat abstract class Kendaraan dengan method abstract pipiKlakson(): string dan method biasa info(): string
  4. Buat class Mobil dan Motor yang extends Kendaraan

Selanjutnya

Kamu sudah paham kontrak dan template di OOP. Lanjut ke Trait → untuk belajar cara berbagi kode antar class tanpa inheritance.