Inheritance and parent::
What you'll learn:
- extend a class with
extends, override its methods and call the parent's version throughparent::; - describe a shared contract with an abstract class or an interface and check it with
instanceof; - plug ready-made methods into a class with a trait and know whose method wins when the names match;
- declare
enumenumerations and get a case from a string withfromandtryFrom.

In the previous theme, a class was a house blueprint and objects were the houses built from it. Now picture a whole family of blueprints. An architect does not redraw a house with a different kitchen from scratch: they take the existing blueprint and write "same as the main one, but a different kitchen".
The new blueprint keeps only the differences and takes the rest from the main one. If someone fixes the main blueprint, the fix shows up in the new one at once. That is why PHP has inheritance: a class receives all the properties and methods of another class and may change some of them.
Without inheritance you would copy the same methods into every similar class, and then fix the same bug in every copy.
extends: everything from the parent
The class you inherit from is called the parent class, and the class that inherits is the child class. You write the link between them with the word extends:
<?php
class Animal
{
public function __construct(protected string $name) {}
public function speak(): string
{
return $this->name . ': hum';
}
}
class Cat extends Animal {}
echo (new Cat('Tom'))->speak(), "\n"; // Tom: humLet's walk through it step by step:
Animalis an ordinary class: it has a constructor that promotes the property$name, and a methodspeak().class Cat extends Animal {}declares a child class with an empty body.Cathas no code of its own, yet it can already do everythingAnimalcan.new Cat('Tom')calls the constructorCatreceived from its parent, and$namegets'Tom'.(new Cat('Tom'))->speak()creates an object and calls a method on it right away.Cathas nospeak()method, so PHP takes the one fromAnimal.
A class in PHP has only one parent: class Cat extends Animal, Pet is a parse error. A parent, on the other hand, may have any number of child classes, and they may have their own.
Overriding and parent::
A child class may declare a method with the same name as the parent's. This is called overriding: objects of the child class use the new version. The parent's version does not disappear, and you can reach it through parent:::
class Dog extends Animal
{
public function speak(): string
{
return $this->name . ': woof';
}
public function greet(): string
{
return parent::speak() . ', ' . $this->speak();
}
}
echo (new Dog('Rex'))->greet(), "\n"; // Rex: hum, Rex: woofLet's see what happens here:
Dogoverridesspeak(): the dog answerswoof, nothum.- Inside
greet(), the callparent::speak()takes the version fromAnimaland gets'Rex: hum'. - The call
$this->speak()in the same method takesDog's own version and gets'Rex: woof'.
Override a method with the same parameters and the same return type as the parent's. A method marked final cannot be overridden: PHP refuses to run such a file and reports a fatal error.
The object picks the method
Say the method talk() is written in Animal and calls $this->speak() inside. Which speak() runs when the object is a Dog?
PHP looks at the class of the object in $this, not at the class where the code is written. So for a Dog object, the code from Animal lands in Dog::speak. Press "Next step" and watch what sits in $this and which speak() opens.
1<?php2 3class Animal4{5 public function speak(): string6 {7 return 'hum';8 }9 public function talk(): string10 {11 return $this->speak() . '!';12 }13}14class Dog extends Animal15{16 public function speak(): string17 {18 return 'woof';19 }20}21 22$a = new Animal();23$d = new Dog();24echo $a->talk(), "\n";25echo $d->talk(), "\n";
A plain Animal object with nothing of Dog in it.
The rule the widget shows:
$thisinside a method is the object the method was called on, even when the method is written in the parent;$this->speak()looks for the method in that object's class first, and only then in its parents.
Here the blueprint picture falls short. In a real house, a room built from the main blueprint knows nothing about the new one. In PHP, the method talk() from Animal asks the object itself how to speak, and a Dog object answers with its own version.
This behavior is called polymorphism: one call works differently depending on the object's class. Interviewers like to ask: "What does $this->method() in the parent's code call when the object is a child?" The answer: the version from the object's class.
The child's constructor
When a child class has its own constructor, it replaces the parent's completely. PHP does not call the parent's constructor by itself, so the child calls it explicitly, through parent::__construct():
class Parrot extends Animal
{
public function __construct(string $name, private string $word)
{
parent::__construct($name);
}
public function speak(): string
{
return $this->name . ': ' . $this->word;
}
}
echo (new Parrot('Kesha', 'hello'))->speak(), "\n"; // Kesha: hello- The
Parrotconstructor takes a name and a word. It keeps the word in its own property$word. - It passes the name to
parent::__construct($name), and theAnimalconstructor writes it into$name. speak()reads both properties and returns'Kesha: hello'.
protected and private
In Animal, the property $name is declared protected, so the methods of Dog and Parrot can read it. Here is how the three visibility levels behave under inheritance:
publicis visible everywhere: in the class itself, in child classes and outside;protectedis visible in the class itself and in all its child classes, but not outside;privateis visible only in the class that declared it.
If $name were private, reading $this->name in a Dog method would give a warning and null instead of the name:
Warning: Undefined property: Dog::$nameIf the parent's property is private, a child class may declare its own property with the same name: it will be a different property. Interviewers often ask about the difference between private and protected under inheritance too.
Common mistake
The child class got its own constructor, and the call to the parent's constructor was forgotten:
class Hamster extends Animal
{
public function __construct(private int $age) {}
}
echo (new Hamster(1))->speak(), "\n"; // ✗Fatal error: Uncaught Error: Typed property Animal::$name must not be accessed before initializationThe Hamster constructor replaced the Animal constructor, and nobody wrote a value into $name. The method speak() reads a property that was never assigned, and PHP stops the script. The fix is to take the name in the constructor and pass it on through parent::__construct($name), as Parrot does.
Key points
class Dog extends Animalgives the child class all the parent's properties and methods; a class has one parent.- An overriding method works for objects of the child class, and the parent's version is reachable through
parent::. $this->method()in the parent's code calls the version from the object's class: that is polymorphism.- A child class with its own constructor calls
parent::__construct()explicitly;protectedis visible in child classes,privateis not.