OOP Lanjutan — PHP

PHP mendukung inheritance, abstract class, dan interface. Inheritance (pewarisan): class Animal { public function __construct(public string $nama) {} public…

Di OOP Dasar kamu bikin satu class lalu beberapa object darinya. Di lesson ini class-class mulai berhubungan: satu class bisa mewarisi isi class lain (inheritance), sebuah class bisa sengaja dibuat belum lengkap supaya anaknya yang melengkapi (abstract class), dan sebuah class bisa berjanji punya method tertentu (interface). Bayangin buku menu Warung Bu Tini. Tiap halaman dicetak dari template yang sama: tempat nama dan harga sudah ada. Kolom "kategori" sengaja dikosongkan di template, tiap halaman wajib mengisinya sendiri, dan template kosong itu gak pernah dijual. Beberapa halaman ditempeli stiker "Bisa Diantar", tanda halaman itu punya tarif ongkir. Template adalah class induk, kolom kosong adalah method abstract, stikernya interface.

🧪 Tebakan cepat: Menu adalah abstract class. Apa yang terjadi kalau kamu menulis new Menu("Nasi Goreng", 15000)? Object-nya jadi tapi kosong, atau PHP menolak? Tebak dulu, jawabannya ada di bagian "Abstract class: induk yang sengaja belum lengkap".

Inheritance: extends mewarisi isi induk

<?php
class Menu {
    public function __construct(public string $nama, public int $harga) {}

    public function info(): string {
        return "$this->nama - Rp$this->harga";
    }
}

class Minuman extends Menu {
    public function info(): string {
        return parent::info() . " (pakai es)";
    }
}

$teh = new Minuman("Es Teh", 5000);
echo $teh->info(); // Es Teh - Rp5000 (pakai es)

Satu class cuma boleh extends satu induk. Siapa yang boleh menyentuh sebuah property atau method diatur visibility-nya:

Kata kunci Bisa dipakai dari Kalau dilanggar dari luar class
public mana saja
protected class itu sendiri dan anak-anaknya Cannot access protected property Menu::$harga
private class itu sendiri saja, anaknya pun gak bisa Cannot access private property Menu::$stok

Abstract class: induk yang sengaja belum lengkap

<?php
abstract class Menu {
    public function __construct(public string $nama, public int $harga) {}

    abstract public function kategori(): string;

    public function info(): string {
        return $this->kategori() . ": $this->nama - Rp$this->harga";
    }
}

class Makanan extends Menu {
    public function kategori(): string {
        return "Makanan";
    }
}

$nasi = new Makanan("Nasi Goreng", 15000);
echo $nasi->info() . "\n";

$menu = new Menu("Nasi Goreng", 15000);
echo "baris ini gak pernah jalan";
$ php menu.php
Makanan: Nasi Goreng - Rp15000

Fatal error: Uncaught Error: Cannot instantiate abstract class Menu in /var/www/warung/menu.php:21
Stack trace:
#0 {main}
  thrown in /var/www/warung/menu.php on line 21

Latihan lesson ini memakai pola yang sama: abstract class Bangun dengan luas() abstract, lalu Lingkaran dan Segitiga yang masing-masing mengisi rumusnya.

Interface: janji punya method tertentu

interface BisaDiantar {
    public function ongkir(int $jarakKm): int;
}

class Makanan extends Menu implements BisaDiantar {
    public function kategori(): string { return "Makanan"; }
    public function ongkir(int $jarakKm): int { return 2000 * $jarakKm; }
}

class Minuman extends Menu implements BisaDiantar {
    public function kategori(): string { return "Minuman"; }
}
$ php menu.php

Fatal error: Class Minuman contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (BisaDiantar::ongkir) in /var/www/warung/menu.php on line 21
Abstract class Interface
Isinya property, constructor, method lengkap, method abstract daftar method tanpa isi
Cara pakai extends, satu induk implements, boleh banyak
Pas untuk anak-anak yang berbagi data dan kode class yang gak bersaudara tapi butuh kemampuan yang sama

💡 final, lalu self:: lawan static::

final mengunci sesuatu supaya gak bisa diubah anaknya:

abstract class Menu {
    // ...
    final public function info(): string {
        return "$this->nama - Rp$this->harga";
    }
}

class Promo extends Menu {
    public function info(): string { return "GRATIS"; }
}
// Fatal error: Cannot override final method Menu::info()

final class Kasir {} mengunci class-nya: class KasirCurang extends Kasir {} ditolak dengan Class KasirCurang cannot extend final class Kasir.

Method static dipanggil lewat nama class dan ::, tanpa object. Di dalamnya, self dan static sama-sama menunjuk class, tapi beda class:

abstract class Menu {
    // ...
    public static function buat(string $nama, int $harga): static {
        return new static($nama, $harga);
    }
}

$nasi = Makanan::buat("Nasi Goreng", 15000);
echo get_class($nasi); // Makanan

💡 Enum dengan method

Enum adalah tipe dengan daftar nilai yang tertutup. Ukuran gelas Es Teh cuma S atau L, gak boleh yang lain:

enum Ukuran: string {
    case Kecil = "S";
    case Besar = "L";

    public function tambahan(): int {
        return match ($this) {
            Ukuran::Kecil => 0,
            Ukuran::Besar => 3000,
        };
    }
}

$u = Ukuran::from("L");
echo $u->name;              // Besar
echo $u->value;             // L
echo 5000 + $u->tambahan(); // 8000
var_dump(Ukuran::tryFrom("XL")); // NULL
Ukuran::from("XL"); // ValueError: "XL" is not a valid backing value for enum Ukuran

⚠️ Jebakan yang sering ketemu

TL;DR: extends membuat class anak mewarisi isi induknya (satu induk saja), method yang ditulis ulang di anak meng-override induk, dan parent:: memanggil versi induk. public bisa dari mana saja, protected dari class itu dan anaknya, private hanya dari class itu sendiri. abstract class gak bisa di-new (Cannot instantiate abstract class) dan method abstract-nya wajib diisi anaknya. interface adalah janji daftar method, dipasang dengan implements (boleh banyak), dan PHP menagihnya saat class dibaca. final mengunci method atau class, new static membuat object dari class yang dipanggil sedangkan new self dari class tempat kodenya ditulis, dan enum adalah daftar nilai tertutup yang boleh punya method. Untuk luas lingkaran pakai M_PI.

Yang akan kamu pelajari