Tutorial PHP #23: Interface, Trait, dan Abstract Class

1. Abstract Class

Abstract class adalah class yang tidak bisa diinstansiasi langsung - harus di-extend dulu. Digunakan sebagai template untuk class-class yang punya karakteristik serupa tapi berbeda implementasinya.

<?php
abstract class Bentuk {
    // Abstract method: tidak punya implementasi, wajib di-override child class
    abstract public function luas(): float;
    abstract public function keliling(): float;

    // Method biasa: punya implementasi, bisa dipakai langsung
    public function info(): string {
        return "Luas: {$this->luas()}, Keliling: {$this->keliling()}";
    }
}

class Persegi extends Bentuk {
    public function __construct(private float $sisi) {}

    public function luas(): float {
        return $this->sisi ** 2;
    }

    public function keliling(): float {
        return 4 * $this->sisi;
    }
}

class Lingkaran extends Bentuk {
    public function __construct(private float $radius) {}

    public function luas(): float {
        return M_PI * $this->radius ** 2;
    }

    public function keliling(): float {
        return 2 * M_PI * $this->radius;
    }
}

$persegi   = new Persegi(5);
$lingkaran = new Lingkaran(7);

echo $persegi->info();    // Output: Luas: 25, Keliling: 20
echo $lingkaran->info();  // Output: Luas: 153.938..., Keliling: 43.982...

// $bentuk = new Bentuk();  // ERROR! Tidak bisa instansiasi abstract class
?>

2. Interface

Interface mendefinisikan "kontrak" - daftar method yang wajib diimplementasikan oleh class yang menggunakannya. Semua method di interface harus public.

<?php
interface Serializable {
    public function toArray(): array;
    public function toJson(): string;
}

interface Validatable {
    public function validate(): bool;
    public function getErrors(): array;
}

// Satu class bisa implement banyak interface
class FormData implements Serializable, Validatable {
    private array $errors = [];

    public function __construct(
        private string $nama,
        private string $email
    ) {}

    public function toArray(): array {
        return ["nama" => $this->nama, "email" => $this->email];
    }

    public function toJson(): string {
        return json_encode($this->toArray());
    }

    public function validate(): bool {
        $this->errors = [];
        if (empty($this->nama))  $this->errors[] = "Nama wajib diisi";
        if (!filter_var($this->email, FILTER_VALIDATE_EMAIL)) {
            $this->errors[] = "Email tidak valid";
        }
        return empty($this->errors);
    }

    public function getErrors(): array {
        return $this->errors;
    }
}

$form = new FormData("Ariq", "ariq@mail.com");
if ($form->validate()) {
    echo $form->toJson();
    // Output: {"nama":"Ariq","email":"ariq@mail.com"}
}
?>

3. Trait

Trait memungkinkan berbagi kode (method) ke beberapa class tanpa inheritance. Solusi untuk masalah PHP yang tidak mendukung multiple inheritance.

<?php
trait Timestamps {
    private ?string $createdAt = null;
    private ?string $updatedAt = null;

    public function setCreatedAt(): void {
        $this->createdAt = date("Y-m-d H:i:s");
    }

    public function setUpdatedAt(): void {
        $this->updatedAt = date("Y-m-d H:i:s");
    }

    public function getCreatedAt(): ?string { return $this->createdAt; }
    public function getUpdatedAt(): ?string { return $this->updatedAt; }
}

trait SoftDelete {
    private bool $deleted = false;

    public function delete(): void {
        $this->deleted = true;
    }

    public function isDeleted(): bool {
        return $this->deleted;
    }

    public function restore(): void {
        $this->deleted = false;
    }
}

class Artikel {
    use Timestamps, SoftDelete;   // pakai dua trait sekaligus!

    public function __construct(public string $judul) {
        $this->setCreatedAt();
    }
}

$artikel = new Artikel("Belajar PHP OOP");
echo $artikel->getCreatedAt();   // Output: timestamp saat ini
echo $artikel->isDeleted();      // Output: false (belum dihapus)
$artikel->delete();
echo $artikel->isDeleted();      // Output: true
?>

4. Kapan Pakai Masing-Masing?

  • Abstract class - ada kode yang bisa dishare, tapi tiap turunan punya implementasi berbeda
  • Interface - mendefinisikan kontrak tanpa implementasi, class bisa implement banyak interface
  • Trait - ingin berbagi method ke beberapa class yang tidak ada hubungan inheritance

5. Ringkasan

  • Abstract class tidak bisa diinstansiasi, gunakan sebagai template class
  • Interface mendefinisikan kontrak method yang wajib diimplementasikan
  • Trait untuk code reuse di class yang berbeda tanpa inheritance langsung
  • Satu class bisa implement banyak interface tapi hanya extend satu class

Tutorial berikutnya membahas namespace dan autoloading.


ariq fadhil

Im Ariq Tech, a Top Rated Fullstack Developer with 5+ years of experience, delivering high-quality solutions across 50+ projects.