Interfaces & Abstract Classes

7 questions found

What is an interface in PHP, and what purpose does it serve in defining a contract for classes to follow?

Beginner
An interface defines a set of method signatures that any class implementing that interface must provide, without specifying any actual implementation details itself, acting as a contract that guarantees any class implementing the interface will have those specific methods available, which lets different parts of your code depend on the interface rather than any particular concrete class, improving flexibility and testability.
interface Shape {
    public function area(): float;
}
class Circle implements Shape {
    public function __construct(private float $radius) {}
    public function area(): float { return M_PI * $this->radius ** 2; }
}
Real-world example A billing system defines a PaymentGateway interface with a charge method, and different concrete classes implement that same interface for different actual payment providers, letting the checkout code work with any provider interchangeably.

Common follow-ups: Can a class implement multiple interfaces at the same time?;What happens if a class does not implement every method required by an interface it claims to implement?

OOP;Dependency Injection & Service Containers

What is an abstract class in PHP, and how does it differ from a regular class and from an interface?

Beginner
An abstract class cannot be instantiated directly and is meant to be extended by other classes, and unlike an interface, it can contain both fully implemented methods that subclasses inherit as is, as well as abstract methods that have no implementation and must be provided by any concrete subclass, making abstract classes useful when you want to share some common implementation logic across related classes while still requiring each subclass to implement certain specific behaviors of their own.
abstract class Shape {
    abstract public function area(): float;
    public function describe(): string {
        return 'This shape has an area of ' . $this->area();
    }
}
Real-world example A shape hierarchy uses an abstract Shape class that provides a shared describe method usable by every subclass, while still requiring each specific shape, such as Circle or Rectangle, to implement its own area calculation method.

Common follow-ups: Can an abstract class implement an interface?;Why might you choose an abstract class over an interface for a specific design situation?

OOP;Design Patterns in PHP

How do you decide whether to use an interface or an abstract class when designing a set of related classes that share common behavior?

Intermediate
You generally choose an interface when you want to define a pure contract without providing any shared implementation, especially when unrelated classes need to guarantee the same set of capabilities, and you choose an abstract class when you have genuinely shared implementation logic that multiple related subclasses can reuse as is, combined with certain behaviors that must still be customized by each specific subclass, keeping in mind that a class can implement multiple interfaces but can only extend a single abstract class.
// Interface: unrelated classes sharing a capability
interface Loggable { public function getLogMessage(): string; }

// Abstract class: related classes sharing implementation
abstract class PaymentMethod {
    public function logTransaction() { /* shared logic */ }
    abstract public function process(float $amount): bool;
}
Real-world example A payment processing system uses an abstract PaymentMethod class to share common transaction logging logic across all payment types, while separately using a Refundable interface that only some, but not all, payment methods choose to implement.

Common follow-ups: Why can a class only extend one abstract class but implement many interfaces?;What is a practical example where both an interface and an abstract class are used together in the same design?

OOP;Design Patterns in PHP

How does PHP's type system use interfaces to enable polymorphism, allowing different concrete classes to be used interchangeably wherever the interface type is expected?

Intermediate
Polymorphism lets you write code that operates on an interface type without needing to know the specific concrete class it is actually working with at runtime, meaning a function accepting a parameter typed to a specific interface can accept any object from any class that implements that interface, and PHP correctly calls whichever specific implementation belongs to the actual object passed in, allowing genuinely flexible, extensible code that can work with new implementations added later without any changes to the code using the interface.
function printArea(Shape $shape) {
    echo $shape->area();
}
printArea(new Circle(5));
printArea(new Rectangle(4, 6));
Real-world example A reporting function accepts any object implementing the Shape interface, correctly calculating and printing the area whether it receives a Circle, a Rectangle, or an entirely new shape class added to the codebase much later.

Common follow-ups: What is the difference between polymorphism achieved through interfaces versus through class inheritance?;How does PHP determine which specific method implementation to actually call at runtime?

OOP;Design Patterns in PHP

Can an interface extend another interface in PHP, and how does this let you build more specific contracts on top of a more general one?

Intermediate
Yes, an interface can extend one or more other interfaces using the extends keyword, meaning any class implementing the more specific extended interface must also fulfill the requirements of the original, more general interface it extends, letting you build up increasingly specific contracts in layers, such as a base Comparable interface extended by a more specific SortableCollection interface that adds additional required methods on top.
interface Comparable {
    public function compareTo($other): int;
}
interface Sortable extends Comparable {
    public function getSortKey(): mixed;
}
Real-world example A collections library defines a base Comparable interface, then a more specific Sortable interface extending it, letting classes implementing Sortable automatically also satisfy the more general Comparable contract without repeating that method's signature.

Common follow-ups: Can an interface extend multiple other interfaces at the same time?;How is extending an interface different from a class implementing multiple interfaces?

OOP;Design Patterns in PHP

How does the Liskov Substitution Principle relate to properly designing interfaces and abstract classes so that subclasses can genuinely be substituted for their parent type without breaking expected behavior?

Advanced
The Liskov Substitution Principle states that objects of a subclass should be usable anywhere an object of the parent class or interface is expected, without altering the correctness of the program, meaning a subclass should honor the behavioral expectations established by its parent, such as not throwing unexpected exceptions for inputs the parent would have accepted, or not weakening guarantees the parent provided, and violating this principle, even while technically satisfying an interface's method signatures, can lead to subtle, hard to diagnose bugs when a specific subclass is substituted in.
// Violates Liskov Substitution Principle
class Bird { public function fly() {} }
class Penguin extends Bird {
    public function fly() { throw new Exception('Penguins cannot fly'); }
}
Real-world example A team refactors a class hierarchy after discovering that a Penguin subclass technically implemented a required fly method but simply threw an exception when called, violating the expectation established by the parent Bird class and causing unexpected failures wherever a generic Bird was expected.

Common follow-ups: How do you redesign a class hierarchy that violates the Liskov Substitution Principle?;What are some other common, subtle ways this principle gets violated in real codebases?

OOP;Design Patterns in PHP

How can PHP's interface based type hinting combined with abstract classes support building a genuinely extensible plugin architecture within an application?

Advanced
By defining a clear interface, such as a PluginInterface with specific required methods, along with an optional abstract base class providing shared boilerplate implementation, an application can dynamically discover and load classes that implement that interface at runtime, letting third party developers or separate teams build entirely new plugins that seamlessly integrate with the core application, as long as they properly implement the required interface, without the core application ever needing to know about those specific plugin implementations in advance.
interface PaymentPlugin {
    public function getName(): string;
    public function process(float $amount): bool;
}
$plugins = [];
foreach (glob('plugins/*.php') as $file) {
    require $file;
}
foreach (get_declared_classes() as $class) {
    if (in_array(PaymentPlugin::class, class_implements($class))) {
        $plugins[] = new $class();
    }
}
Real-world example An e commerce platform defines a PaymentPlugin interface and automatically discovers and loads any class in its plugins directory that implements it, letting third party developers add entirely new payment provider integrations without ever needing to modify the platform's own core codebase.

Common follow-ups: What security considerations arise from dynamically loading plugin code discovered at runtime?;How do popular content management systems like WordPress implement similar extensibility patterns?

Design Patterns in PHP;WordPress Plugin & Theme Development