A child class can override a method: write a method with the same name and replace the parent’s behaviour.
<?php
class Animal
{
public function speak(): string
{
return "Some sound";
}
}
class Cat extends Animal
{
public function speak(): string
{
return "Meow";
}
}
class Cow extends Animal {}
echo (new Cat())->speak() . "\n";
echo (new Cow())->speak();
Meow
Some sound
Cat replaced speak(). Cow kept the parent’s version.
Extend, do not only replace: parent::
Often you want to add to the parent’s behaviour. Call it with parent::.
<?php
class Notification
{
public function message(): string
{
return "You have a new notification.";
}
}
class UrgentNotification extends Notification
{
public function message(): string
{
return "URGENT: " . parent::message();
}
}
echo (new UrgentNotification())->message();
URGENT: You have a new notification.
Polymorphism in action
Code that works with the parent type calls the right method automatically.
<?php
class Animal
{
public function speak(): string { return "..."; }
}
class Dog extends Animal
{
public function speak(): string { return "Woof"; }
}
class Cat extends Animal
{
public function speak(): string { return "Meow"; }
}
foreach ([new Dog(), new Cat(), new Animal()] as $animal) {
echo $animal->speak() . " ";
}
Woof Meow ...
This is explained further in Polymorphism.
Signature rules
An overriding method must be compatible with the parent’s:
- It must accept at least the same parameters (it may add optional ones).
- Its return type must be the same or narrower (more specific).
- It may not make the method less visible (a
publicmethod cannot becomeprotected).
<?php
class Base
{
public function load(string $name): string
{
return $name;
}
}
class Child extends Base
{
public function load(int $name): string
{
return "changed";
}
}
Fatal error: Declaration of Child::load(int $name): string must be compatible with Base::load(string $name): string in /path/to/index.php on line 12
The rule exists so that a Child can be used anywhere a Base is expected without surprises.
The Override attribute (PHP 8.3+)
Marking an override with #[\Override] makes PHP check that the parent really has that method. It catches typos and parent renames.
<?php
class Cat extends Animal
{
#[\Override]
public function speek(): string // typo: a fatal error, because Animal has no speek()
{
return "Meow";
}
}
On PHP before 8.3, the attribute is simply ignored (it is a comment to the engine), so it does no harm.
Preventing overrides
A method marked final cannot be overridden. See Final.
Silent typos
#[\Override], a mistyped method name does not override anything. It creates a new method, and the parent’s one still runs. Be careful with names, or use the attribute.