पाठ 8 / 25

Inheritance, Interfaces, Abstract Classes and Traits

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
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.

त्वरित जाँच: What does the #[\Override] attribute (PHP 8.3) do?

  • It makes a method final
  • It hides the parent method
  • It enables traits
  • 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.