What's the Difference?

Both Abstract Classes and Interfaces are cornerstones of professional OOP. They allow us to define a "contract" or a "blueprint" that other classes must follow. This forces our code to be more predictable, organized, and scalable. However, they serve slightly different purposes.

  • Abstract Class: Think of it as a "partially built house." It can define some complete methods (walls that are already built) but also declares some abstract methods that child classes must build themselves (rooms you have to finish). A class can only extend one abstract class.
  • Interface: Think of it as a "blueprint only." It contains no implementation at all, only method signatures that a class must define. It's a pure contract. A class can implement multiple interfaces.

1. Abstract Classes

An abstract class is a class that cannot be instantiated on its own. It's meant to be inherited by other classes.

Key Rules:

  • Declared with the abstract keyword.
  • Can contain regular methods with full implementation.
  • Can contain "abstract methods," which have no body and must be implemented by the child class.
  • A class can only extend one abstract class.

Example:


// This class cannot be created directly: new Shape(); would fail.
abstract class Shape {
    protected $name;

    public function __construct($name) {
        $this->name = $name;
    }

    // A regular method that all children will inherit
    public function getName() {
        return $this->name;
    }

    // An abstract method. The child class MUST define this.
    abstract public function calculateArea();
}

class Circle extends Shape {
    private $radius;

    public function __construct($radius) {
        parent::__construct("Circle");
        $this->radius = $radius;
    }

    // Implementing the abstract method from the parent
    public function calculateArea() {
        return pi() * ($this->radius * $this->radius);
    }
}

class Square extends Shape {
    private $side;

    public function __construct($side) {
        parent::__construct("Square");
        $this->side = $side;
    }

    // Implementing the abstract method from the parent
    public function calculateArea() {
        return $this->side * $this->side;
    }
}

$circle = new Circle(10);
echo $circle->getName() . " Area: " . $circle->calculateArea(); // Outputs: Circle Area: 314.15...

echo "<br>";

$square = new Square(10);
echo $square->getName() . " Area: " . $square->calculateArea(); // Outputs: Square Area: 100

2. Interfaces

An interface is a pure blueprint. It defines which methods a class must have, but it doesn't provide any of the code for how those methods work.

Key Rules:

  • Declared with the interface keyword.
  • All methods in an interface are automatically abstract and public. You don't need to type it.
  • Interfaces cannot have properties (except for constants).
  • A class uses the implements keyword and can implement multiple interfaces at once.

Example:


// A contract for things that can be logged
interface Loggable {
    public function getLogMessage();
}

// A contract for things that can be saved
interface Savable {
    public function saveToDatabase();
}

class User implements Loggable, Savable { // Implementing two interfaces!
    private $username;

    public function __construct($username) {
        $this->username = $username;
    }

    public function getLogMessage() {
        return "User '{$this->username}' was processed.";
    }

    public function saveToDatabase() {
        echo "Saving user '{$this->username}' to the database...";
        // In a real app, database logic would go here.
    }
}

$user = new User("startwithsite");
echo $user->getLogMessage(); // Outputs: User 'startwithsite' was processed.
echo "<br>";
$user->saveToDatabase(); // Outputs: Saving user 'startwithsite' to the database...

When to Use Which?

  • Use an Abstract Class when you have a group of related classes that share common functionality (an "is-a" relationship, e.g., a Circle is a Shape).
  • Use an Interface when you want to define a capability that unrelated classes can share (a "has-a" or "can-do" relationship, e.g., a User can be Loggable, a Product can be Loggable).