Property, Method & Visibility
Atur akses: public, protected, private, dan kenapa enkapsulasi itu penting.
Analogi: Brankas vs Etalase Toko
Toko punya etalase (boleh dilihat dan disentuh pengunjung) dan brankas (hanya pemilik yang boleh buka). Visibility di OOP membedakan hal yang sama: public = etalase (boleh diakses dari luar), private = brankas (hanya dari dalam class), protected = ruang staf (class ini + turunannya).
Kenapa tidak semua public saja? Karena data yang bisa diubah sembarang orang dari luar akan rusak dengan cara tak terduga. Visibility adalah kontrak: "bagian ini stabil dan aman dipakai, bagian itu urusan internal yang bisa berubah sewaktu-waktu".
<?php
// Contoh 1: private + getter/setter (pola paling penting di OOP)
class Rekening {
private float $saldo = 0;
public function setor(float $jumlah): void {
if ($jumlah <= 0) {
throw new InvalidArgumentException("Setoran harus positif");
}
$this->saldo += $jumlah;
}
public function tarik(float $jumlah): void {
if ($jumlah > $this->saldo) {
throw new RuntimeException("Saldo tidak cukup");
}
$this->saldo -= $jumlah;
}
public function getSaldo(): float {
return $this->saldo;
}
}
$r = new Rekening();
$r->setor(100000);
$r->tarik(25000);
echo $r->getSaldo(); // 75000
// $r->saldo = 99999999; // ERROR: private! tidak bisa diakali dari luarTanpa private, siapa pun bisa menulis $r->saldo = -5000 atau 99999999 dan merusak logika. Dengan private + method, setiap perubahan wajib lewat aturan (tidak negatif, tidak melebihi saldo). Inilah yang disebut encapsulation.
<?php
// Contoh 2: protected untuk inheritance
class Pegawai {
protected string $nama;
protected float $gajiPokok;
public function __construct(string $nama, float $gajiPokok) {
$this->nama = $nama;
$this->gajiPokok = $gajiPokok;
}
public function getNama(): string {
return $this->nama; // boleh: dari dalam class sendiri
}
}
class Manajer extends Pegawai {
public function getGaji(): float {
return $this->gajiPokok * 2; // boleh: protected terlihat oleh anak
}
}
$m = new Manajer("Sinta", 5000000);
echo $m->getGaji(); // 10000000
// echo $m->gajiPokok; // ERROR: protected, tidak bisa dari luarprotected adalah jalan tengah: disembunyikan dari dunia luar, tapi dibuka untuk class turunan yang memang perlu memakainya.
Jebakan yang Sering Terjadi
Semua public "biar gampang". Gampang hari ini, mimpi buruk 6 bulan lagi saat 50 tempat mengubah property langsung dan satu perubahan aturan merusak semuanya. Aturan praktis: mulai dari private, naikkan ke protected/public hanya saat ada kebutuhan nyata.
Getter/setter tanpa logika. setNama($n) { $this->nama = $n; } yang tidak memvalidasi apa pun sama saja dengan public. Setter harus melakukan sesuatu: validasi, normalisasi, atau trigger. Kalau tidak ada logika, pertimbangkan property public readonly.
Membaca UML Sederhana
Diagram class UML memakai simbol visibility yang wajib dikenal:
+= public (contoh:+getSaldo())-= private (contoh:-saldo)#= protected (contoh:#gajiPokok)
+------------------+
| Rekening |
+------------------+
| -saldo: float |
+------------------+
| +setor(j): void |
| +getSaldo(): float|
+------------------+Membaca diagram ini: class Rekening punya property private $saldo bertipe float, method public setor dan getSaldo. Kemampuan membaca UML (meski sederhana) sangat membantu saat membaca dokumentasi library dan framework.
Catatan teknis: PHP 8.1+ punya
public readonly string $nama;: bisa dibaca dari luar tapi hanya bisa diisi sekali (di constructor). Cocok untuk data yang tidak boleh berubah seperti ID atau tanggal dibuat.
Tantangan
Dompet digital
Buat class Dompet dengan private $saldo. Method: isi($jumlah) (tolak <= 0), bayar($jumlah) (tolak jika saldo kurang, return bool), getSaldo(). Uji: isi 50000, bayar 20000 (berhasil), bayar 40000 (gagal).