PHP Pandas: Inheritance

← Back to Index

When a mommy panda and a daddy panda love each other very much, they might decide to have baby pandas together. Of course, I'm not talking about those lazy black and white pandas. They aren't very parentally motivated. I mean the beautiful red ones.

The baby pandas will likely share a number of properties with their parents. Not only their bright fluffy coat, but also their eating habits, sleeping patterns, and general personality. They inherit these properties from their parents.

If I wanted a biology lesson, I'd have bought a biology book.

Well look at you! Aren't you a little antsy today?

Well, as it happens, pandas aren't the only things that inherit properties. You see, classes can also have parents. I'm not entirely sure how the breeding takes place, but I can certainly teach you about the result.

Let's take a look at a simple class.

<?php

class Panda
{
    // Properties
    var $coat = 'fluffy';
    var $colour;

    // Method
    function getCoat()
    {
        return $this->coat;
    }

    // Method
    function getColour()
    {
        return $this->colour;
    }
}

Here's our simple class. It's got two properties, $coat and $color. We've also got class methods called getCoat() and getColour(), which simply return our property values. It doesn't get more simple, does it? You've got this buddy!

Let's push our comfort zones. Let's do something new.

 <?php

class Panda
{
    // Properties
    var $coat = 'fluffy';
    var $colour;

    // Method
    function getCoat()
    {
        return $this->coat;
    }

    // Method
    function getColour()
    {
        return $this->colour;
    }
}

class GiantPanda extends Panda
{
    // DUN DUN DUUUUUUN!
}

Hurray! There's some new syntax. That means that we're about to add a new tool to our arsenal!

What's this extends keyword doing? We're actually telling PHP that the GiantPanda class should inherit from the Panda class. You could say that the GiantPanda class is going to borrow genetic material from the Panda. This means that GiantPanda gains access to all of the properties and methods from Panda.

Prove it!

Oh yeah? Don't believe me? I'm going to prove it so darn hard! In the next section, just imagine that the class definitions are still there. I'm gonna omit them for clarity. I don't want to be one of those cheesy authors who duplicate a bunch of code just to get more pages in! We're friends now! I'd never do that to you. Now don't you feel guilty for not trusting me?

 <?php

// Create a new giant panda instance.
$giantPanda = new GiantPanda;

// Get coat type.
echo $giantPanda->getCoat();

We create a new instance of the GiantPanda class and call the getCoat() method on it. We echo out the value, because we're going to want to see the result. Let's take a look at the output.

fluffy

Awww. It's so fluffy I'm gonna die!

As you can see, our giant panda has inherited both the getCoat() method, and the $coat property (with default value) from its panda parent.

While red pandas and giant pandas are similar, the coats of the giant pandas are less fluffy, so we need to represent this in our GiantPanda class. Let's try it!

 <?php

class Panda
{
    // Properties
    var $coat = 'fluffy';
    var $colour;

    // Method
    function getCoat()
    {
        return $this->coat;
    }

    // Method
    function getColour()
    {
        return $this->colour;
    }
}

class GiantPanda extends Panda
{
    var $coat = 'less fluffy';
}

In the above example, we have overridden the $coat property from the Panda class. Within the GiantPanda class, we redeclare $coat as 'less fluffy'. We haven't changed the getCoat() method at all. Let's try calling this method now.

 <?php

// Create a new giant panda instance.
$giantPanda = new GiantPanda;

// Get coat type.
echo $giantPanda->getCoat();

This time we receive new output...

{title="Example 07: Output."} less fluffy

As you can see, the getCoat() method in the parent Panda class respects our change to the $coat variable in the child GiantPanda class. It returns the value less fluffy. We've overridden the value of this field.

We can also override class methods from parent classes. All you need to do is re-declare the property or method that you want to override in the child class.

If it's not clear yet, the 'parent' class is the class that you extend. In the above example, the parent class is Panda. The 'child' class is the one that implements the extend keyword. This was GiantPanda in the previous example.

Classes can have a limitless chain of inheritance. Here's an example of four classes which are part of an inheritance chain.

 <?php

class First
{
    var $legendary = 'Barney Stinson';
}

class Second extends First
{

}

class Third extends Second
{

}

class Fourth extends Third
{

}

In the above example:

  • Second inherits from First
  • Third inherits from Second
  • Fourth inherits from Third

I like to call this an inheritance chain. It looks like this:

First <-- Second <-- Third <-- Fourth

Of course, all four classes have access to a $legendary property, with the value of 'Barney Stinson'.

Type-hinting classes

In a previous chapter, we discovered how to type hint function parameters so that we can ensure that they are of the correct type. We demonstrated this technique using arrays, but they aren't the only types of variables that can be type-hinted.

In PHP functions and methods, we can type-hint classes. With a parameter type-hinted to a class, only instances of the specified class can be passed to the method or function.

Let's demonstrate this functionality by first creating two classes.

 <?php

class Sephiroth
{
    function equipWeapon(Weapon $weapon)
    {
        echo 'Die cloud die!';
    }
}

class Weapon
{

}

Our first class, Sephiroth has a single method called equipWeapon(), which has a parameter type-hinted to the second class named Weapon. (Don't worry about the functionality of the equipWeapon() method for now, we're merely thinking about structure at this point.) This means that you will only be able to pass instances of the Weapon class as parameters for this method.

Let's attempt this.

<?php

// Instantiate a Sephiroth class.
$sephiroth = new Sephiroth;

// Instantiate a Weapon class.
$weapon = new Weapon;

// Call the equipWeapon() method.
$sephiroth->equipWeapon($weapon);

If we execute the code, we see the 'Die cloud die!' message that we expect. Go ahead and try changing the type of the parameter passed to the equipWeapon() method. I can assure you, PHP will not be pleased.

Earlier, I told you that only instances of the type-hinted class would be allowed, but actually, I lied a little. You see, you can also pass classes which inherit from the type-hinted class. Let's see this in action.

 <?php

class Sephiroth
{
    function equipWeapon(Weapon $weapon)
    {
        echo 'Die cloud die!';
    }
}

class Weapon
{

}

class Masamune extends Weapon
{

}

class Murasame extends Weapon
{

}

// Instantiate a Sephiroth class.
$sephiroth = new Sephiroth;

// Instantiate a Masamune class.
$masamune = new Masamune;

// Instantiate a Murasame class.
$murasame = new Murasame;

// Call the equipWeapon() method with masamune.
$sephiroth->equipWeapon($masamune);

// Call the equipWeapon() method with murasame.
$sephiroth->equipWeapon($murasame);

We've added added two new classes, Masamune and Murasame, which extend the Weapon parent class. Since they both have Weapon as a parent class, we can pass their instances to methods which type-hint Weapon.

In a later chapter, we're going to take a look at a special structure called an interface and you'll see how type-hinting combined with interfaces can lead to some extremely useful tricks!

My books are available online for free to encourage learning. However, if you'd like for me to keep writing, then please consider buying a digital copy over at Leanpub.com.

It's available in PDF, ePub, and Kindle format, and contains a bunch of extras that you won't find on the site. I have a full-time job, and I write my books in my spare time. Please consider buying a copy so that I can continue to write new books from the comfort of my sofa!