Interfaces vs Abstract Classes
Knowing when to use an interface vs an abstract class is one of the most common PHP OOP interview questions. The answer depends on whether you're defining a capability contract or sharing implementation.
<?php
// Interface: WHAT a class must do (contract/capability)
interface Cacheable {
public function getCacheKey(): string;
public function getCacheTtl(): int;
public function serialize(): string;
}
interface Searchable {
public function getSearchableText(): string;
public function getSearchWeight(): float;
}
// Class can implement MULTIPLE interfaces
class Post implements Cacheable, Searchable {
public function getCacheKey(): string { return 'post:' . $this->id; }
public function getCacheTtl(): int { return 3600; }
public function serialize(): string { return json_encode($this->toArray()); }
public function getSearchableText(): string { return $this->title . ' ' . $this->content; }
public function getSearchWeight(): float { return 1.0; }
}
// Abstract class: shared implementation + forced overrides
abstract class BaseRepository {
protected PDO $db;
public function __construct(PDO $db) {
$this->db = $db; // concrete — shared by all children
}
// Concrete method — all children inherit this
public function beginTransaction(): void {
$this->db->beginTransaction();
}
// Abstract — each child MUST implement
abstract public function findById(int $id): ?array;
abstract public function save(array $data): int;
abstract protected function getTable(): string;
// Template Method pattern
public function findAll(): array {
return $this->db->query("SELECT * FROM {$this->getTable()}")->fetchAll();
}
}
class UserRepository extends BaseRepository {
protected function getTable(): string { return 'users'; }
public function findById(int $id): ?array {
$s = $this->db->prepare('SELECT * FROM users WHERE id=?');
$s->execute([$id]);
return $s->fetch() ?: null;
}
public function save(array $data): int {
$s = $this->db->prepare('INSERT INTO users (name,email) VALUES (?,?)');
$s->execute([$data['name'], $data['email']]);
return (int)$this->db->lastInsertId();
}
}
| Feature | Interface | Abstract Class |
|---|---|---|
| Multiple inheritance | Yes (implement many) | No (extend one) |
| Constructor | Not allowed | Allowed |
| Properties | Constants only | Any visibility |
| Method bodies | No (abstract only) | Mix of both |
| Use when | Defining capability | Sharing implementation |
Comments (0)
No comments yet. Be the first!
Leave a Comment