Sejauh ini setiap class yang kita tulis selalu punya nama dan berdiri sebagai deklarasi terpisah. Kadang-kadang kita hanya butuh class yang dipakai tepat satu kali di satu tempat: satu pembanding kecil untuk satu pemanggilan fungsi, atau satu implementasi interface untuk keperluan pengujian. Memaksa class seperti itu menempati nama global dan berdiri jauh dari lokasi pemakaiannya justru membuat kode sulit dibaca. PHP menyediakan anonymous class — class tanpa nama yang dideklarasikan dan diinstansiasi dalam satu ekspresi new class. Pada chapter ini kita akan belajar sintaksnya, cara mengirim data ke dalamnya, dan kapan class anonim menjadi pilihan yang tepat.
Membuat Class Tanpa Nama #
Anonymous class ditulis dengan new class diikuti body di dalam kurung kurawal, lalu diakhiri titik koma karena keseluruhannya adalah ekspresi. Hasil ekspresi tersebut adalah object biasa yang bisa disimpan ke variabel dan dipakai seperti object dari class bernama:
<?php
$sapa = new class {
public function halo(string $nama): string
{
return "Halo, $nama!";
}
};
echo $sapa->halo("Budi") . "\n";Output yang Dihasilkan:
Halo, Budi!Ekspresi new class { ... } melakukan dua hal sekaligus: mendeklarasikan class tanpa nama, lalu menginstansiasi object dari class tersebut. Variabel $sapa kini memegang object yang utuh — lengkap dengan method halo() yang bisa dipanggil berulang kali. Anonymous class juga mengikuti aturan warisan biasa: class anonim bisa extends class lain, implements interface, bahkan keduanya sekaligus:
<?php
class SapaanDasar
{
public function sapa(): string
{
return "Halo";
}
}
$sapaanRamah = new class extends SapaanDasar {
public function sapa(): string
{
return parent::sapa() . ", selamat datang!";
}
};
echo $sapaanRamah->sapa() . "\n";Output yang Dihasilkan:
Halo, selamat datang!Class anonim di atas mewarisi SapaanDasar, meng-override method sapa(), dan tetap bisa memanggil versi parent lewat parent::sapa(). Seluruh materi inheritance dan method overriding dari chapter sebelumnya berlaku tanpa perubahan — satu-satunya hal yang hilang hanyalah nama class-nya.
Mengirim Data dari Luar lewat Constructor #
Anonymous class bisa menerima constructor arguments persis seperti class bernama — argumen ditulis langsung setelah kata class. Inilah satu-satunya jalur resmi untuk membawa nilai dari luar ke dalam class anonim:
<?php
$faktorPengali = 3;
$kalkulator = new class ($faktorPengali) {
public function __construct(private int $faktor)
{
}
public function hitung(int $nilai): int
{
return $nilai * $this->faktor;
}
};
echo "7 x 3 = " . $kalkulator->hitung(7) . "\n";Output yang Dihasilkan:
7 x 3 = 21Nilai $faktorPengali dikirim lewat constructor argument, lalu disimpan ke property $faktor lewat constructor promotion. Method hitung() kemudian memakai property tersebut untuk menghitung hasil.
Implementasi Interface Sekali Pakai #
Kombinasi paling umum dari anonymous class adalah implementasi interface yang hanya relevan di satu titik kode. Kita mendeklarasikan interface untuk kontrak, lalu menyediakan implementasinya tepat di tempat object tersebut dibutuhkan:
<?php
interface PengubahTeks
{
public function ubah(string $teks): string;
}
function prosesTeks(string $teks, PengubahTeks $pengubah): string
{
return $pengubah->ubah($teks);
}
$hasil = prosesTeks("belajar php", new class implements PengubahTeks {
public function ubah(string $teks): string
{
return strtoupper($teks);
}
});
echo $hasil . "\n";Output yang Dihasilkan:
BELAJAR PHPFungsi prosesTeks() hanya mengenal kontrak PengubahTeks, sehingga implementasi konkret bebas ditulis di tempat lain — termasuk sebagai class anonim yang dilempar langsung sebagai argumen. Pola ini menjaga fungsi tetap terbuka terhadap perilaku baru tanpa menuntut class bernama untuk setiap variasi.
Test Double dengan Anonymous Class #
Pemanfaatan paling berharga dari anonymous class di dunia nyata adalah membuat test double: implementasi palsu yang ringan untuk keperluan pengujian. Misalkan layanan pendaftaran bergantung pada interface NotifikasiInterface; dalam pengujian kita tidak ingin benar-benar mengirim email, cukup merekam bahwa pemanggilan terjadi:
<?php
interface NotifikasiInterface
{
public function kirim(string $penerima, string $pesan): bool;
}
class LayananPendaftaran
{
public function __construct(private NotifikasiInterface $notifikasi)
{
}
public function daftar(string $email): string
{
$sukses = $this->notifikasi->kirim($email, "Selamat datang!");
return $sukses ? "terdaftar + notifikasi terkirim" : "terdaftar tanpa notifikasi";
}
}
$notifikasiRekaman = new class implements NotifikasiInterface {
public array $penerimaTerkirim = [];
public function kirim(string $penerima, string $pesan): bool
{
$this->penerimaTerkirim[] = $penerima;
return true;
}
};
$layanan = new LayananPendaftaran($notifikasiRekaman);
$layanan->daftar("[email protected]");
$layanan->daftar("[email protected]");
echo "Notifikasi terkirim ke: " . implode(", ", $notifikasiRekaman->penerimaTerkirim) . "\n";Output yang Dihasilkan:
Notifikasi terkirim ke: [email protected], [email protected]Mari kita bedah contoh di atas:
LayananPendaftaranbergantung pada interface: layanan tidak tahu apa pun tentang email sungguhan — hanya kontrakkirim().- Class anonim sebagai test double: implementasi palsu menyimpan setiap penerima ke array
$penerimaTerkirimdan selalu melaporkan sukses, sehingga pengujian tidak menyentuh jaringan. - Pemeriksaan hasil: setelah
daftar()dipanggil dua kali, isi array membuktikan bahwa notifikasi tepat terkirim ke dua alamat yang benar.
Class anonim seperti ini membuat pengujian berjalan tanpa layanan eksternal — teknik yang akan kita pakai intensif pada Section Testing dan Quality Assurance. PHPUnit bahkan menyediakan pembuat test double otomatis, namun anonymous class tetap berguna untuk kasus sederhana tanpa dependensi tambahan.
Nama Class Anonim #
Setiap class di PHP tetap punya nama internal meskipun kita tidak memberinya nama. Memanggil get_class() pada object anonim menghasilkan nama berbentuk class@anonymous diikuti path berkas, nomor baris, dan angka alamat internal — misalnya class@anonymous/app/src/index.php:9:39. Karena nama tersebut mengandung alamat yang bisa berbeda di setiap eksekusi, nama tersebut tidak boleh dicetak sebagai output contoh maupun dipakai sebagai dasar keputusan program:
<?php
interface Penghitung
{
public function hitung(): int;
}
$hitung = new class (5) implements Penghitung {
public function __construct(private int $nilai)
{
}
public function hitung(): int
{
return $this->nilai * 2;
}
};
// Nama dari get_class($hitung) berbentuk:
// "class@anonymous/path/ke/berkas.php:9:39"
// Bagian angka di akhir berisi alamat internal yang berubah
// antar eksekusi, jadi nama ini tidak boleh dicetak langsung.
var_dump($hitung instanceof Penghitung);
echo $hitung->hitung() . "\n";Output yang Dihasilkan:
bool(true)
10Pemeriksaan identitas yang tepat untuk object anonim adalah instanceof terhadap class atau interface yang dikenalnya — bukan membandingkan nama internal. Jika suatu saat Anda melihat nama class@anonymous... muncul di pesan error atau stack trace, itulah tanda bahwa error tersebut berasal dari class anonim di berkas dan baris yang disebutkan.
Kapan Memakai Anonymous Class #
Anonymous class adalah alat yang ringkas, bukan pengganti class bernama. Gunakan anonymous class ketika:
- implementasi hanya dipakai di satu titik kode dan tidak akan dibagikan;
- Anda butuh test double atau stub kecil di dalam berkas pengujian;
- Anda ingin meng-override satu-dua method dari class yang ada untuk satu kebutuhan khusus.
Hindari anonymous class ketika:
- logikanya cukup panjang sehingga body besar mengganggu alur pembacaan;
- implementasi dipakai di lebih dari satu tempat — beri nama dan biarkan di-autoload;
- Anda perlu merujuk class tersebut dari tempat lain, misalnya sebagai type declaration.
Jika Anda mendapati diri sendiri menulis class anonim di dalam class anonim, pertimbangkan untuk mengangkat salah satunya menjadi class bernama.
Ringkasan #
Anonymous class menggabungkan deklarasi dan instansiasi dalam satu ekspresi new class, menerima data lewat constructor argument, serta tetap tunduk pada aturan extends, implements, dan instanceof. Class tanpa nama ini bersinar untuk implementasi sekali pakai dan test double, sementara nama internal class@anonymous... cukup dipahami sebagai penjejak asal-usul di pesan error. Fleksibilitas PHP dalam menciptakan class ternyata juga berlaku ke arah sebaliknya: mengunci class agar tidak bisa diubah siapa pun. Mekanisme penguncian itu bernama final, yang kita bahas pada chapter berikutnya.