# Inheritance, Interfaces, Abstract Classes and Traits — PHP

Source: https://www.skillbyai.com/en/php/o-inherit

> Reuse behaviour with interfaces, abstract classes and traits, and know their trade-offs.

## Sharing contracts and code

A class can **extend** one parent class and **implement** many **interfaces**. Interfaces declare method signatures (and constants) that implementations must provide, so code can depend on contracts such as `PaymentGateway` rather than concrete classes. **Abstract classes** combine partial implementations with abstract methods for subclasses to fill in. **`final`** prevents a class from being extended or a method from being overridden, a good default for classes not designed for inheritance. Use **`#[\Override]`** (PHP 8.3) on overriding methods so PHP errors if the parent method does not exist, catching typos and refactoring mistakes. **Traits** provide **horizontal code reuse**: a trait's methods and properties are copied into each class that uses it (`use Timestamps;`). Traits are handy for small, cross-cutting helpers, but heavy trait use hides dependencies and makes classes hard to follow; prefer composition, injecting a collaborator object, for real behaviour. PHP supports **late static binding** with `static::` so factory methods return the subclass that called them.

## Interface, abstract class, final and a trait

Checkout depends on the interface; a trait adds small shared behaviour.

```php
<?php
declare(strict_types=1);

interface PaymentGateway
{
    public function charge(string $orderId, int $amountPaise): PaymentResult;
}

abstract class HttpGateway implements PaymentGateway
{
    public function __construct(protected readonly HttpClient $http) {}

    abstract protected function endpoint(): string;

    public function charge(string $orderId, int $amountPaise): PaymentResult
    {
        $response = $this->http->post($this->endpoint(), ['order' => $orderId, 'amount' => $amountPaise]);
        return PaymentResult::fromArray($response);
    }
}

trait LogsCalls
{
    private function logCall(string $what): void
    {
        error_log(static::class . ': ' . $what);
    }
}

final class UpiGateway extends HttpGateway
{
    use LogsCalls;

    #[\Override]
    protected function endpoint(): string
    {
        $this->logCall('endpoint resolved');
        return 'https://payments.example.com/upi/charge';
    }
}
```

## A job description, a template and a toolkit

An interface is a job description (what must be done), an abstract class is a half-filled template (some steps done for you), and a trait is a toolkit you hand to several workers. Hand out too many toolkits and nobody remembers who owns which tool.

**Quiz:** What does the #[\Override] attribute (PHP 8.3) do?

- [ ] It makes a method final
- [ ] It hides the parent method
- [ ] It enables traits
- [x] It causes an error if the method does not actually override a parent or interface method

*Answer:* It causes an error if the method does not actually override a parent or interface method. #[\Override] turns accidental non-overrides, such as typos, into errors.
