PHP 8: Modern PHP Development · Object-Oriented PHP 8
Interfaces, Abstract Classes and Traits
Model contracts and share behavior without deep inheritance hierarchies.
Interfaces define contracts (method signatures, constants); a class can implement many. Abstract classes share code and state while leaving some methods abstract; a class extends only one. Traits copy methods (and properties) into classes for horizontal reuse. Prefer interfaces plus composition; use abstract classes for template-method style shared behavior; use traits sparingly for small cross-cutting helpers. Since 8.2 traits can define constants, and since 8.3 class constants can be typed.
<?php
interface PaymentGateway
{
public function charge(Money $amount, string $token): ChargeResult;
}
abstract class HttpGateway implements PaymentGateway
{
public function __construct(protected readonly HttpClient $http) {}
protected function post(string $url, array $body): array
{
return $this->http->post($url, ['json' => $body])->toArray();
}
}
trait LogsCalls
{
private function logCall(string $method, array $context = []): void
{
$this->logger->info("Calling {$method}", $context);
}
}
final class StripeGateway extends HttpGateway
{
use LogsCalls;
public function __construct(HttpClient $http, private LoggerInterface $logger) { parent::__construct($http); }
public function charge(Money $amount, string $token): ChargeResult { /* ... */ }
}
Common pitfalls
- Deep inheritance trees that are hard to change — favor composition.
- Traits that depend on undeclared properties of the host class (use abstract methods in the trait to require them).
- Interfaces with too many methods; keep them small (Interface Segregation).
Key points
- Depend on interfaces, not implementations
- Abstract classes share code; interfaces define contracts
- Use traits sparingly
Further reading: PHP manual: interfaces
Practice questions
When would you choose an abstract class over an interface?
Answer
When implementations share real code or state (e.g., a base HTTP gateway with helper methods). Interfaces are for contracts; you can combine both: an interface for the type, an abstract class as a convenient base.
What problem do traits solve, and what's their main risk?
Answer
They allow reusing methods across unrelated classes without inheritance. Risks: hidden coupling to host class internals, name conflicts, and code that's hard to follow when overused.
Open in the app to mark lessons complete, take notes and track your progress.