Black Friday Black Friday
Black Friday ultimate sale! Get up to 80 % extra free points! More information here

Lesson 7 - Inheritance in PHP

PHP OOP Inheritance in PHP

In the previous tutorial, Reference and primitive data types in PHP, 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

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.


 

Download

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

 

 

Article has been written for you by David Capka
Avatar
Do you like this article?
No one has rated this quite yet, be the first one!
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 College The author learned IT at the Unicorn College - a prestigious college providing education on IT and economics.
Activities (11)

 

 

Comments

Avatar
Justin Jake Telo:9. February 22:33

<?php

// Contents of the Human.php file
class Human
{

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

public function __construct($fir­stName, $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;
}

}

// Contents of the PhpProgrammer.php file
class PhpProgrammer extends Human
{

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

}
//Contents of the webDeveloper.php file
class webDeveloper extends Human
{
public function webdev()
{
echo("hi im " . $this->firstName . " I'm a web developer...");
}
}

// Contents of the index.php file

require_once('clas­ses/Human.php');
require_once('clas­ses/PhpProgram­mer.php');

$carl = new Human('Carl', 'Smith', 30);
$john = new PhpProgrammer('Joh­n', 'Newman', 24);
$tin = new webDeveloper('Tin','T­elo',28);

$carl->run(10);
$carl->run(10);
$carl->run(10);
$john->greet();
echo('
');
$john->program();
echo('
');
$tin->webdev();
$tin->run(400);
// $carl->webdev(); cant' call its decedant 'WebDeveloper Class';
/* $john->webdev(); this is an error this parent the parents of webDeveloper
'$jonh-> = new PhpProgrammer'*/

 
Reply 9. February 22:33
Avatar
Justin Jake Telo:9. February 22:39

im talking the parents and child ('ancestor and descendant')
decendant can use the method of their ancestor but the ancestor can't use the methods of its decendants.. but why there is code that extends it for there relationship please enlighten me

 
Reply 9. February 22:39
Avatar
Justin Jake Telo:10. February 0:36

can you help me on this.. i got to call the protected method in via $carl = new Human and protected function tin() inside the class of human i once call it but i got this result

PHP Fatal error: Call to protected method Human::tin() from context '' in /home/jailphp/5a7e8309­70c31/index.php on line 77

here's ,my code

<?php

// Contents of the Human.php file
class Human
{

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

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

protected function sleep($time)
{
$this->tiredness -= $time * 10;
if ($this->tiredness < 0)
$this->tiredness = 0;
}
protected function tin(){
echo ($this->firstName . " " . $this->lastName);
}

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;
}

}

// Contents of the PhpProgrammer.php file
class PhpProgrammer extends Human
{

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

}

// Contents of the index.php file
require_once('clas­ses/Human.php');
require_once('clas­ses/PhpProgram­mer.php');

$carl = new Human('Carl', 'Smith', 30);
$john = new PhpProgrammer('Joh­n', 'New', 24, 'Eclipse');

//$john->greet(); it work
//$carl->program(); it doesn't work
//$john->tin(); not working called in PhpProgrammer instanceprotected!!
//$carl->tin(); not working called in Human Class protected
//$carl->tin(); not working called in Human Class protected

?>

 
Reply 10. February 0:36
Avatar
David Capka
ICT.social team
Avatar
Replies to Justin Jake Telo
David Capka:10. February 4:56

Hi Justin,
you can call protected methods only from within the class. Only public methods can be called on the variable carrying the instance. You can call $this->tin() anywhere in the code of the PhpProgrammer class, but not outside of it.

Edited 10. February 4:56
Reply  +1 10. February 4:56
You can walk through a storm and feel the wind but you know you are not the wind.
Avatar
Justin Jake Telo:10. February 7:59

Thans david i fiugre it our.. like

class human {

protected function tin(){
echo ($this->firstName . " " . $this->lastName);
}
class PhpProgrammer extends human{

public function zion() {
echo $this->tin();
}
}
include(classes­s/Human.php);

$carl = new human();
$joseph = new PhpProgrammer();

$joseph->zion(); // in this i can call protected methods in parent human

 
Reply  +1 10. February 7:59
To maintain the quality of discussion, we only allow registered members to comment. Sign in. If you're new, Sign up, it's free.

5 messages from 5 displayed.