Inheritance lets a class reuse and extend another class's behavior with extends:
class Animal
{
public function __construct(protected string $name) {}
public function speak(): string
{
return "{$this->name} makes a sound.";
}
}
class Dog extends Animal
{
public function speak(): string
{
return "{$this->name} barks."; // overrides the parent method
}
public function fetch(): string
{
return "{$this->name} fetches the ball.";
}
}
$dog = new Dog('Rex');
echo $dog->speak(); // 'Rex barks.'
Call the parent implementation from a child with parent::speak(), and prevent further overriding of a method or extending of a class with the final keyword.
Abstract classes cannot be instantiated directly — they define a partial contract that subclasses must complete:
abstract class Shape
{
abstract public function area(): float; // no body — subclasses must implement it
public function describe(): string
{
return 'Area: ' . $this->area();
}
}
class Circle extends Shape
{
public function __construct(private float $radius) {}
public function area(): float
{
return pi() * $this->radius ** 2;
}
}
Abstract classes are useful when you want to share some common implementation across subclasses while still forcing each one to implement specific methods.