Get up to 80 % extra points for free! More info:

Lesson 7 - Inheritance in PHP

In the previous exercise, Solved tasks for OOP in PHP lessons 4-6, we've practiced our knowledge from previous lessons.

In the previous tutorial, Solved tasks for OOP in PHP lessons 4-6, we went over the differences between reference and primitive data types. Today, we will go even deeper into the world of object-oriented programming. In the first lesson, I told you all that OOP is built upon 3 pillars: encapsulation, inheritance and polymorphism. We've already gone into encapsulation, i.e. class method/property modifiers. Today is all about inheritance.

Inheritance

Inheritance is one of the main principles of OOP and is used when creating new data structures based on old ones. We'll apply all of these concepts to our Human instances.

In case you forgot, our humans are able to greet, sleep and run. However, let's say we wanted to add a PHP programmer to our application. He/she will be able to do the same as things a regular human can and also be able to program.

Start by adding a new class file named PhpProgrammer.php to the classes folder. Essentially, we could just copy the Human class over and add a program() method to it:

<?php

class PhpProgrammer
{

    public $firstName;
    public $lastName;
    public $age;
    private $tiredness = 0;

    public function __construct($firstName, $lastName, $age)
    {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
        $this->age = $age;
    }

    public function sleep($time)
    {
        $this->tiredness -= $time * 10;
        if ($this->tiredness < 0)
            $this->tiredness = 0;
    }

    public function run($distance)
    {
        if ($this->tiredness + $distance <= 20)
            $this->tiredness += $distance;
        else
            echo("I'm too tired.");
    }

    public function greet()
    {
        echo('Hi, my name is ' . $this->firstName);
    }

    public function program()
    {
        echo("I'm programming...");
    }

    public function __toString()
    {
        return $this->firstName;
    }

}

This code is very redundant. If we wanted to change something in Human, we'd have to change it here as well as in other similar classes. Hopefully, you agree that this is not the best way to extend an application.

Instead, we'll modify our new class using inheritance:

<?php

class PhpProgrammer extends Human
{

    public function program()
    {
        echo("I'm programming...");
    }

}

PHP will now inherit the PhpProgrammer from the Human class. To do this, we used the "extends" keyword, which takes all of the methods and properties from an ancestor class and adds them to an ancestor class.

As you may have noticed, I also added a program() method to the class. Let's modify index.php to make $john a PhpProgrammer. I also made him program and greet so you see that the PhpProgrammer class truly is derived from the Human class:

require_once('classes/Human.php');
require_once('classes/PhpProgrammer.php');

$carl = new Human('Carl', 'Smith', 30);
$john = new PhpProgrammer('John', 'Newman', 24);

$carl->run(10);
$carl->run(10);
$carl->sleep(1);
$carl->run(10);
$john->greet();
echo('<br />');
$john->program();
class Human
{

    public $firstName;
    public $lastName;
    public $age;
    private $tiredness = 0;

    public function __construct($firstName, $lastName, $age)
    {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
        $this->age = $age;
    }

    public function sleep($time)
    {
        $this->tiredness -= $time * 10;
        if ($this->tiredness < 0)
            $this->tiredness = 0;
    }

    public function run($distance)
    {
        if ($this->tiredness + $distance <= 20)
            $this->tiredness += $distance;
        else
            echo("I'm too tired.");
    }

    public function greet()
    {
        echo('Hi, my name is ' . $this->firstName);
    }

    public function __toString()
    {
        return $this->firstName;
    }

}
class PhpProgrammer extends Human
{

    public function program()
    {
        echo("I'm programming...");
    }

}

Everything works as expected. John has all of the Human class' methods and properties along with the ones we added to the PhpProgrammer class:

Your page
localhost

Inheritance benefits

Surely, you see the benefits of inheritance. This way, we don't have to write the same exact stuff over and over. We get to focus on new functionality, and the rest gets inherited. The benefits are astronomical, we can extend pre-existing components, i.e. re-use them. We don't have to write loads of redundant (duplicated) code, and most importantly, when we change something in the parent class, the changes are inherited everywhere else automatically. Thanks to that, we won't ever have to go back and change 20 classes, forget something in one, and end up causing an error. We are human beings and we will always make mistakes, so we have to use programming techniques to minimize the odds of us making mistakes.

Sometimes, the parent class is referred to as the "ancestor" (the Human class) and the class that inherits from the ancestor, the "descendant" (the PhpProgrammer class). The descendant can have methods all to itself or modify the methods provided by the parent class (see below). You may also encounter similar terms such as "subclass" and "superclass".

In object modeling, the notation for inheritance is an empty arrow pointing to an ancestor.

Object inheritance – graphical notation - Object-Oriented Programming in PHP

Programming languages that support inheritance either support simple inheritance, where the class inherits from a single class - or multiple inheritance, where the class inherits from several classes at a time. Multiple inheritance is not a very common thing to use, you'll see why later on. I will also show you a work-around to this limitation. PHP only supports simple inheritance. Multiple inheritance is found in languages such as C++. As you may have guessed, a descendant can have other descendants and so on.

Inheritance and constructors

Let's add another property to our PhpProgrammer, an IDE (Integrated Development Environment), that he/she will use to program.

Add $ide as a public property to PhpProgrammer class:

public $ide;

Then, modify the program() method so that it prints out which IDE the programmer is using:

public function program()
{
    echo("I'm programming in {$this->ide}...");
}

Calling a parent constructor

Let's make it so that we can set the $ide property in the PhpProgrammer's constructor. PHP inherited the constructor from the ancestor, so now that we need a new constructor, we'll have to "re-declare" it.

It should have all of the parameters needed to create the ancestor + any properties that the descendant requires. Since we have to set the ancestor's properties in the ancestor's constructor, we'll do it in a way that it doesn't re-initialize the object. We'll do this by setting the PhpProgrammer's properties and setting the rest by calling the ancestor's constructor. To do that we use a parent variable. Don't worry about the double colon operator, we'll get to it in future lessons.

public function __construct($firstName, $lastName, $age, $ide)
{
    $this->ide = $ide;
    parent::__construct($firstName, $lastName, $age);
}

Last of all, modify John's declaration in index.php :

$john = new PhpProgrammer('John', 'New', 24, 'Eclipse');
class Human
{

    public $firstName;
    public $lastName;
    public $age;
    private $tiredness = 0;

    public function __construct($firstName, $lastName, $age)
    {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
        $this->age = $age;
    }

    public function sleep($time)
    {
        $this->tiredness -= $time * 10;
        if ($this->tiredness < 0)
            $this->tiredness = 0;
    }

    public function run($distance)
    {
        if ($this->tiredness + $distance <= 20)
            $this->tiredness += $distance;
        else
            echo("I'm too tired.");
    }

    public function greet()
    {
        echo('Hi, my name is ' . $this->firstName);
    }

    public function __toString()
    {
        return $this->firstName;
    }

}
class PhpProgrammer extends Human
{

    public $ide;

    public function __construct($firstName, $lastName, $age, $ide)
    {
        $this->ide = $ide;
        parent::__construct($firstName, $lastName, $age);
    }

    public function program()
    {
        echo("I'm programming in {$this->ide}...");
    }

}

Application output:

Your page
localhost

Protected modifier

In the example above, the parent's private properties won't be accessible to the descendant. All we can access from there is public properties and methods. Private properties and methods are seen as hidden class logic, which is kept from the descendant. In other words, it can use them, but it can't change them. You can check for yourself, a PhpProgrammer can sleep, but we cannot access the $tiredness property directly. This way, every human will be able to sleep in the same way without directly modifying the parent's method.

If we wanted to make a property (or a method) inaccessible from the outside, but accessible for descendants, we would use a protected access modifier. Let's add another method to the Human class, that returns his/her full name ($firstName + $lastName). We will only be able to use this method from inside of the class and from inside classes that inherit from it. To do so, we will mark it as protected:

protected function fullName()
{
    return $this->firstName . ' ' . $this->lastName;
}

We won't be able to call the method in index.php, but we will be able to call it from within the Human class as well as from within the PhpProgrammer class. We will continue on this topic in the next lesson, Polymorphism, final attributes and autoloader in PHP, as well as get into polymorphism.


 

Did you have a problem with anything? Download the sample application below and compare it with your project, you will find the error easily.

Download

By downloading the following file, you agree to the license terms

Downloaded 34x (2.74 kB)
Application includes source codes in language PHP

 

Previous article
Solved tasks for OOP in PHP lessons 4-6
All articles in this section
Object-Oriented Programming in PHP
Skip article
(not recommended)
Polymorphism, final attributes and autoloader in PHP
Article has been written for you by David Capka Hartinger
Avatar
User rating:
1 votes
The author is a programmer, who likes web technologies and being the lead/chief article writer at ICT.social. He shares his knowledge with the community and is always looking to improve. He believes that anyone can do what they set their mind to.
Unicorn university David learned IT at the Unicorn University - a prestigious college providing education on IT and economics.
Activities