100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
PHP

Inheritance and Interfaces

Understand how PHP classes extend one another via single inheritance and implement contracts via interfaces, including method overriding rules.

Object-Oriented PHPIntermediate10 min readJul 9, 2026
Analogies

Inheritance and Interfaces

Inheritance lets a class (a subclass) reuse and extend the properties and methods of another class (its parent) using the extends keyword, modeling an 'is-a' relationship such as a SavingsAccount being a kind of Account. PHP supports only single inheritance — a class may extend exactly one parent class — but a class can implement any number of interfaces via implements, which is how PHP achieves multiple-contract polymorphism without the ambiguity of multiple class inheritance. An interface declares a set of public method signatures (and optionally constants) that any implementing class must provide, without specifying how those methods work.

🏏

Cricket analogy: A SavingsAccount extending Account is like a T20 match extending the general rules of cricket, adding its own powerplay restrictions on top of the base laws of the game, an 'is-a' relationship of match format to sport.

Extending Classes and Overriding Methods

A subclass inherits all non-private members of its parent and may override any inherited method by redeclaring it with the same signature (or a compatible, covariant one). Inside an overriding method, parent::methodName() calls the parent's original implementation, which is the standard way to extend rather than fully replace inherited behavior — for example, calling parent::__construct() to run the parent's initialization logic before adding subclass-specific setup.

🏏

Cricket analogy: Calling parent::methodName() when overriding is like a new captain running the standard warm-up drill their predecessor established before adding their own personal fielding-practice twist on top, rather than scrapping the routine entirely.

php
class Account
{
    public function __construct(protected float $balance = 0.0) {}

    public function deposit(float $amount): void
    {
        $this->balance += $amount;
    }

    public function describe(): string
    {
        return sprintf('Balance: %.2f', $this->balance);
    }
}

class SavingsAccount extends Account
{
    public function __construct(float $balance, private readonly float $interestRate)
    {
        parent::__construct($balance);
    }

    public function describe(): string
    {
        return parent::describe() . sprintf(' (rate %.1f%%)', $this->interestRate * 100);
    }
}

Defining and Implementing Interfaces

An interface is declared with the interface keyword and lists method signatures with no bodies (except default constant values it may declare). A class opts into an interface's contract with implements, and must define every method the interface declares, with a matching (or covariant) signature, or PHP raises a fatal error. Since PHP 8.1, interfaces themselves can also declare enum-friendly constants and be composed via extends between interfaces (an interface can extend multiple other interfaces, unlike classes).

🏏

Cricket analogy: An interface listing method signatures with no bodies is like the laws of cricket specifying that a bowler must deliver the ball within the crease, without dictating exact bowling action, and since PHP 8.1 an interface can extend multiple other interfaces, like ICC playing conditions building on several base rule sets.

php
interface Payable
{
    public function amountDue(): float;
}

interface Printable
{
    public function toReceipt(): string;
}

class Invoice implements Payable, Printable
{
    public function __construct(private float $total) {}

    public function amountDue(): float
    {
        return $this->total;
    }

    public function toReceipt(): string
    {
        return sprintf('Invoice total: %.2f', $this->total);
    }
}

function charge(Payable $item): void
{
    echo $item->amountDue();
}

Why Prefer Interfaces to Inheritance in Many Designs

Because PHP only allows one parent class, deep inheritance hierarchies can quickly become rigid and force awkward compromises when a class genuinely needs behavior from two unrelated lineages. Interfaces avoid this by letting a class fulfill many independent contracts (a User might implement both Authenticatable and Notifiable), while composition (holding another object as a collaborator rather than inheriting from it) is often preferred over deep inheritance chains for sharing implementation, keeping each class focused and the overall design easier to change.

🏏

Cricket analogy: Deep inheritance chains are like trying to make a player be both a specialist opener and a death-over finisher through one rigid batting lineage; interfaces let a User implement both Authenticatable and Notifiable the way a player can simply hold two independent skills, opener and finisher, as separate contracts rather than forcing one twisted lineage.

A widely used design guideline is 'program to an interface, not an implementation': functions and methods should accept parameters typed as an interface (like Payable) rather than a concrete class, so any object fulfilling that contract can be passed in, including test doubles, without the function needing to know or care about the concrete class.

Overriding a method with an incompatible signature — for example narrowing a parameter type in a way the parent didn't allow, or changing visibility to be more restrictive than the parent declared — violates PHP's Liskov-substitution-oriented type variance rules and will raise a fatal error at declaration time, not just a warning.

  • extends creates single inheritance between two classes; implements lets a class fulfill any number of interface contracts.
  • Overriding methods can call the parent's original implementation via parent::methodName().
  • Interfaces declare method signatures (and optionally constants) with no implementation bodies; implementing classes must satisfy every declared method.
  • Unlike classes, interfaces can extend multiple other interfaces at once.
  • Overriding method signatures must remain compatible (covariant) with the parent/interface declaration or PHP raises a fatal error.
  • Favor typing against interfaces and using composition over deep inheritance chains for flexible, decoupled design.

Practice what you learned

Was this page helpful?

Topics covered

#PHP#PHPProgrammingStudyNotes#Programming#InheritanceAndInterfaces#Inheritance#Interfaces#Extending#Classes#OOP#StudyNotes#SkillVeris