PHP Class Inheritance

Class inheritance is a basic concept of Object-Oriented Programming.

In this tutorial we are going to see how PHP class inheritance works, including the most important keywords and some code examples.

Contents


Here is how class inheritance works.

First, you define the base class, also called the parent class.
This class represents a general structure or concept.

For example, you can define a Bird class that represents a generic bird. Not any bird in particular, but the generic idea of a bird.

Once you have your base class, you can define children classes. Children classes are also called derived or inherited classes.
Each child class represents a specific case of the base class.

For example, you can define a Parrot class and an Owl class, which are specific cases of Birds:

Now, when you create an object of a child class, this object is also an object of the parent class.
For instance, an object of the Parrot class is also an object of the Bird class. And just the same, an Owl object is also a Bird object.

It makes sense, right? Every specific bird is also a “bird” in the general sense.

But the opposite is not true. If you create a generic Bird object (that is, an object of the base class), this object is not a Parrot or any other child class object.

Now that the relation between base classes and children classes is clear, let’s see how inheritance works in PHP.


How to Inherit Classes in PHP: the extends Keyword

In PHP, you can create a child class from a base class by using the extends keyword.

Let’s see how it works.

First, let’s define the base class, including some properties and methods:


class Bird
{
   public $wingspan;
   public $colors;
   
   public function eat(string $food)
   {
      echo "I'm eating " . $food;
   }
}

Now, let’s define the Parrot child class.

To tell PHP that Parrot is a child class of Bird, you must use the extends keyword using this syntax:


class Parrot extends Bird
{
   //...
}

This makes the Parrot class a specific type of Bird.

Remember how objects of the child class are also objects of the parent class?
It means that, if you create a Parrot object, this object is a Parrot as well as a Bird.

Therefore, if your code expects a Bird object, you can use a Parrot object too.

For example, let’s say that you have a function that takes a Bird object as argument:


function watchBird(Bird $bird)
{
   echo 'Here is a bird!';
}

$bird = new Bird();
watchBird($bird);

The watchBird() function takes a Bird object as argument.

But a Parrot object works too, because Parrot objects are also Bird objects:


$parrot = new Parrot();
watchBird($parrot); /* This works just fine. */

However, you cannot do the opposite.

If your function expects a Parrot, then you cannot pass a Bird because a Bird is not necessarily a Parrot:


function watchParrot(Parrot $parrot)
{
   echo 'Here is a parrot!';
}

$bird = new Bird();
watchParrot($bird); /* Error: $bird is not a Parrot. */

Inherited Properties and Methods

When you define a child class, this class inherits the public and protected properties and methods from the base class.

In our case, the Parrot child class inherits the public and protected properties and methods from the Bird base class.

For example:


class Bird
{
   public $wingspan;
   public $colors;
   
   public function eat(string $food)
   {
      echo "I'm eating " . $food;
   }
}

class Parrot extends Bird
{
}

$parrot = new Parrot();

/* Public properties inherited from the Bird base class. */
echo $parrot->wingspan;
echo $parrot->colors;

/* Public method inherited from the Bird base class. */
$parrot->eat('berry');

Note that private properties and methods are not available in the child class. Only public and protected ones are.

Children classes can also add their own properties and methods.

This makes sense when you want to implement properties and methods specific for a child class, but that are not relevant for the parent class

For example, parrots can speak some words, but not all birds can.
Therefore, you can add a speak() method to the Parrot class only, without affecting the base Bird class and others Bird’s children classes:


class Parrot extends Bird
{
   public function speak(string $word)
   {
      echo $word;
   }
}

$parrot = new Parrot();
$parrot->speak("hello!");

/* The following does not work: only Parrots have the speak() method. */
$bird = new Bird();
$bird->speak("hello!"); // Error: method "speak" does not exist.

Method Overriding

In a child class, you can use the public and protected methods taken from the base class, as well as create new properties and methods.

But there is one more thing you can do: define a different version of a base class’ method.

This operation is called method overriding.

The idea is to use a method from the base class and make it work in a different way for the child class only.

To do that, you need to define the method again in the child class using the same function name.

Like this:


class Bird
{
   public function eat(string $food)
   {
      echo "I'm eating " . $food;
   }
}

class Parrot extends Bird
{
   public function eat(string $food)
   {
      echo "I'm a parrot and I'm eating " . $food;
   }
}

When you override a method, you must follow two rules:

  1. The method visibility must be equal or more permissive than the base class’ method.

So, if the parent’s method is protected, the child’s method can be protected or public.

And if the parent’s method is public, then the child’s method must be public.

(Note that, if the base class method is private, then the child class cannot see it and method overriding does not apply).

For instance:


class Bird
{
   public function func1() {}
   protected function func2() {}
}

class Parrot extends Bird
{
   private function func1() {}  // ERROR: funct1 must be public
   protected function func1() {}  // ERROR: funct1 must be public
   public function func1() {}  // OK
   
   private function func2() {}  // ERROR: funct2 must be protected or public
   protected function func2() {}  // OK
   public function func2() {}  // OK
}

2. The new method’s arguments must be compatible with the base class method.

This means that any arguments list that is valid for the parent’s method, it must be valid for the child’s method too.

For example, the following argument list is valid because the additional argument has a default value. Therefore, every base class method argument list is also valid in the child class method:


class Bird
{
   public function func1(string $a, int $b) {}
}

class Parrot extends Bird
{
   public function func1(string $a, int $b, bool $c = true) {} // OK
}

The only exception to rule #2 is the class constructor method.

The child constructor can have different arguments than the base class constructor.

For example:


class Bird
{
   public function __construct(string $a, int $b) {}
}

class Parrot extends Bird
{
   // OK even with different arguments.
   public function __construct(bool $a, string $b, int $c) {}
}

The parent:: Keyword

Let’s say that the parent Bird class has a buildNest() public method.
And in the child Parrot class, you want to override this method.

However, you don’t want to write all the method implementation again.
What you want to do is to add a few more lines of code to the parent class’ method.

How can you do that, without writing all the code again?

You need a way to call the parent’s method, instead of the class own method.

To do that, you need to use the parent:: keyword.

Here is how it works:


class Bird
{
   public function buildNest()
   {
      $this->findTree();
      $this->chooseBranch();
      $this->collectStraw();
   }
}

class Parrot extends Bird
{
   public function buildNest()
   {
      parent::buildNest(); // Do all the stuff from the parent class' method.
      $this->speak('Nest done!');
   }
}

In the previous example, the Parrot method calls parent::buildNest() to execute all the operations that the parent class’ method does. After that, it calls the Parrot’s own method speak().

Without the parent:: keyword, you’d have to write all the parent’s method code again.

Note that you can call any of the parent’s methods from any of the child’s methods, as long as the parent’s method is not private.

Inheritance Levels

Child classes can have their own children, too.

For example, you can define a class that represents a specific variety of parrots, like the cockatoo.
In this case, you can extends the Parrot class like this:


class Bird
{
   //...
}

class Parrot extends Bird
{
   //...
}

class Cockatoo extends Parrot
{
   //...
}

All the rules that apply for the Bird->Parrot inheritance, also apply to the Parrot->Cockatoo inheritance.

Note that an object of the Cockatoo class is also a Parrot as well as a Bird.

The final Keyword

The final PHP keyword prevents inheritance.

You can use it in two ways: on the whole class, or on a single method.

If you use it for the whole class, then this class cannot be inherited. For example:


final class Bird
{
   //...
}

class Parrot extends Bird
{
   //...
}

If you run the previous code, you will get this error:

Fatal error: Class Parrot may not inherit from final class (Bird)

If you use final on a class method, then that method cannot be overridden by children classes.

For example:


final class Bird
{
   public function buildNest() {
     //...
   }
   
   final public function layEgg() {
     //...
   }
}

class Parrot extends Bird
{
   public function buildNest() {
     // This is fine.
   }
   
   public function layEgg() {
     // Error: cannot override a final method.
   }
}

Conclusion

In this tutorial you learned the basics of PHP Class Inheritance, including how to use the most important inheritance keywords: extends, parent and final.
You also learned how methods are inherited in children classes and how to override them.

There will be more tutorials about OOP.
If there are specific topics you would like me to write about, let me know in the comments.

Be sure to subscribe to my free newsletter to get my weekly tips!

Alex

Get my best PHP tips and advice every week, absolutely free.

The images used in this article have been downloaded from Freepik:
Designed by Titusurya / FreepikDesigned by macrovector / Freepik