Lesson 9 / 10

Traits and Abstract Classes

Traits — reusable method sets

trait Loggable {n    public function log(string $message): void {n        echo "[" . static::class . "] $messagen";n    }n}nnclass Course {n    use Loggable;n}nn$course = new Course();n$course->log("Created");   // [Course] Created

PHP classes can only extends one parent, but they can use multiple traits at once. A trait shares real method implementations across otherwise unrelated classes without forcing them into a shared parent class — useful when several unrelated classes need the exact same small piece of behavior, like logging, without an artificial inheritance relationship between them.

Abstract classes

abstract class Notifier {n    abstract public function send(string $message): void;nn    public function announce(string $message): void {n        $this->send("[Tutoline] $message");n    }n}nnclass EmailNotifier extends Notifier {n    public function send(string $message): void {n        echo "Emailing: $messagen";n    }n}

An abstract class can’t be instantiated directly with new — it defines a contract that subclasses must fill in (send), while still sharing common, already-implemented logic like announce() above. This mirrors exactly the same pattern you would find in Java’s abstract classes.

Interfaces, briefly

interface Cacheable {n    public function getCacheKey(): string;n}nnclass Course implements Cacheable {n    public function getCacheKey(): string {n        return "course_" . $this->title;n    }n}

Where an abstract class can share real implementation, an interface defines only the method signatures a class promises to provide, with zero implementation of its own — the same distinction covered in the Java course. A PHP class can implements multiple interfaces at once, even though it can only extends one class.