Menu
Coddy logo textTech

Interface vs Abstract Class

Part of the Object Oriented Programming section of Coddy's PHP journey — lesson 30 of 91.

Now that you've learned both interfaces and abstract classes, let's clarify when to use each. While they may seem similar, they serve different purposes and have distinct capabilities.

Feature Interface Abstract Class
Methods Only method signatures Both abstract and concrete methods
Properties Only constants Can have properties
Multiple inheritance A class can implement many A class can extend only one
Constructor Not allowed Can have constructor

Use an interface when you want to define a contract that unrelated classes can fulfill. For example, both a Printer and a Logger might implement a Writable interface, even though they share no common ancestor.

Use an abstract class when you have related classes that share common code. If your Dog and Cat classes both need the same eat() method implementation, an abstract Animal class lets you write that code once.

You can also combine both approaches. A class can extend an abstract class while implementing multiple interfaces:

<?php
abstract class Animal {
    protected $name;
    
    public function eat() {
        return $this->name . " is eating";
    }
}

interface Swimmable {
    public function swim();
}

class Duck extends Animal implements Swimmable {
    public function __construct($name) {
        $this->name = $name;
    }
    
    public function swim() {
        return $this->name . " is swimming";
    }
}

Key Point: Choose interfaces for defining capabilities across unrelated classes. Choose abstract classes when you need to share code among related classes.

challenge icon

Challenge

Easy

Let's build a vehicle system that demonstrates when to use an abstract class versus an interface — and how to combine both approaches effectively.

You'll create a system where vehicles share common properties through inheritance, but can also gain additional capabilities through interfaces. This mirrors real-world design decisions: a car "is a" vehicle (inheritance), but it also "has the capability" to be refuelable (interface).

Organize your code across four files:

  • Refuelable.php — Define a Refuelable interface with a single method signature: refuel($amount). This capability can apply to any class that needs refueling, regardless of its inheritance hierarchy.
  • Vehicle.php — Define an abstract Vehicle class that provides shared functionality for all vehicles. It should have a protected $brand property and a protected $fuelLevel property (starting at 0). The constructor accepts the brand name. Include a concrete getBrand() method that returns the brand, a concrete getFuelLevel() method that returns the current fuel level, and an abstract drive() method that child classes must implement.
  • Car.php — Create a Car class that extends Vehicle and implements Refuelable. Include both required files at the top. The constructor accepts the brand and passes it to the parent constructor. Implement drive() to return "[brand] car is driving". Implement refuel($amount) to add the amount to the fuel level and return "[brand] refueled to [fuelLevel] liters".
  • main.php — Include the Car file. You'll receive two inputs: a brand name and a fuel amount (convert to integer). Create a Car with the brand. Print the result of drive() on the first line, then print the result of refuel() with the fuel amount on the second line.

This challenge illustrates the key distinction: the abstract Vehicle class shares code and establishes an "is-a" relationship, while the Refuelable interface adds a capability that could apply to other unrelated classes (like a generator or a boat) without requiring them to be vehicles.

Cheat sheet

Interfaces and abstract classes serve different purposes:

Feature Interface Abstract Class
Methods Only method signatures Both abstract and concrete methods
Properties Only constants Can have properties
Multiple inheritance A class can implement many A class can extend only one
Constructor Not allowed Can have constructor

Use an interface to define a contract for unrelated classes. Use an abstract class to share common code among related classes.

A class can extend an abstract class while implementing multiple interfaces:

<?php
abstract class Animal {
    protected $name;
    
    public function eat() {
        return $this->name . " is eating";
    }
}

interface Swimmable {
    public function swim();
}

class Duck extends Animal implements Swimmable {
    public function __construct($name) {
        $this->name = $name;
    }
    
    public function swim() {
        return $this->name . " is swimming";
    }
}

Try it yourself

<?php
require_once 'Car.php';

// Read input
$brand = trim(fgets(STDIN));
$fuelAmount = intval(trim(fgets(STDIN)));

// TODO: Create a Car with the brand

// TODO: Print the result of drive() on the first line

// TODO: Print the result of refuel() with the fuel amount on the second line
?>
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming