Understanding Class Inheritance (Child and Parent Classes) in Object-Oriented PHP

Catahoula Puppy | PHP object-oriented programming Dog class

Last time, we covered the fundamentals of object-oriented programming (OOP) in PHP: what an object is, what a class is, and how they interact.

Today, we’re going to cover an intermediate OOP topic: how class inheritance allows for parent classes and child classes in OO PHP, and why those are useful programming concepts.

Class inheritance is really an “Aha!” moment that builds on the lovely intuitiveness of OOP itself, and adds a simple and powerful new feature: the world’s not only full of objects, but some objects are types of other objects. In other words, a plum and a peach are both kinds of fruit—and now we can say that. In PHP!

Leaving fruit aside, we’re going to extend our Dog class example from the previous article to our discussion of class inheritance. What can we say: we’re Dog people.

Let’s get into it! Here’s an introduction to class inheritance in PHP.

What “Class Inheritance” Means in Object-Oriented PHP

In object-oriented programming, class inheritance refers to the ability of one class to extend—and be a child class of—another class. So right off the bat, here’s some language to get straight:

If class Golden_Retriever extends class Dog, that means that class Golden_Retriever is a child class of class Dog. That also means that class Dog is the parent class (also called the base class) of class Golden_Retriever.

As you can see, class inheritance in OO PHP breaks into two fundamental concepts:

  1. Parent classes (also called “base classes”), which define the properties and methods of both themselves and child classes; and
  2. Child classes, which inherit properties and methods from parent classes.

Let’s look at an example that spells out this relationship in detail, and starts to get into the object-oriented PHP code that defines parent and child classes.

Code Example: Dog, Catahoula_Dog, and Golden_Retriever_Dog Classes

We’ll step through an example with one parent class, Dog, and two child classes, Catahoula_Dog and Golden_Retriever_Dog, giving code examples for each.

The Parent Class: Dog

From our last article, we’ve got a simple class, Dog. Here’s the code to register it:

class Dog {
    public $color;
    private $noiselevel;

    public function bark() {
        if( $this->noiselevel === 'loud' ) :
                echo 'BARK';
        else :
                echo 'arf';
        endif;
    }
}

That’s our base class or parent class. It’s the “blueprint” for any number of Dog objects that you would create with $fido = new Dog();, each of whom has a color and can bark either loudly or softly.

Is good doggo.

Our First Child Class: Catahoula_Dog

Of course, there aren’t just “dogs” in the world: there are lots of types of dogs. These types, while all having the basic properties and behaviors of a dog, are also unique in many different ways.

For example, where Fred lives, in Louisiana, they have a breed of dog called a Catahoula that has a special property: a really amazingly patterned coat.

Catahoula is a type of dog. It inherits everything that’s always true about dogs (they have a color and can bark), but it adds something on top: a new property (a coat pattern).

Here’s how that looks in code:

class Catahoula_Dog extends Dog {
    public $coat_patterns = array( 'spots', 'stripes', 'other' ); 
}
Catahoula Puppy

Are you serious

The magic keyword in the code above is extends. Our child class, Catahoula_Dog, is a child class that extends its parent class, Dog. When we write that magic extends keyword, something critical happens: Catahoula_Dog inherits all the properties and methods of the Dog parent class.

Let’s give you some code to show what we mean:

class Catahoula_Dog extends Dog {
    public $coat_patterns = array( 'spots', 'stripes', 'other' ); 
}

$rover = new Catahoula_Dog();
$patterns = $rover->coat_patterns; // $patterns is now an array containing 'spots', 'stripes', 'other'
$rover->bark(); // Prints "arf" (!)

Whoa! How did we get Rover to bark? bark() is not a method we defined in the Catahoula_Dog class.

The answer—and this is the magic of class inheritance—is that Rover inherited the bark() method from Catahoula_Dog‘s parent class, Dog.

Make sense? Let’s give a second example.

Our Second Subclass: Golden_Retriever_Dog

Of course, there are other types of dog than just Catahoulas. How about golden retrievers? Like any dog, they have a color and can bark, but they’ve also got a special property: huge floppy ears. Beyond that, they’ve got a special method: a strong instinct to fetch() things.

class Golden_Retriever_Dog extends Dog {
    public $ear_shape = 'floppy';

    public fetch( $thrown_thing ) {
        return 'Here is ' . $thrown_thing . '!!!';
    }
}
golden retriever dog

Hnnnnggg

Now, what’s the effect of registering a property and method only in this child class? Let’s have a look:

class Golden_Retriever_Dog extends Dog {
    public $ear_shape = 'floppy';

    public fetch( $thrown_thing ) {
        return 'Here is ' . $thrown_thing . '!!!';
    }
}

$max = new Golden_Retriever_Dog();
echo $max->ear_shape; // Prints "floppy"
echo $max->fetch( 'stick' ); // Prints "Here is stick!!!"

echo $max->bark(); // Prints "arf" thanks to inheritance from parent class, Dog
$patterns = $max->coat_patterns; // Uh oh! Golden_Retriever_Dogs don't have a coat_patterns property

See? the Golden_Retriever_Dog has a special property, ear_shape, that we’ve never bothered to specify for any other dog.

Max can also now do a special method: he can fetch() a stick (or anything). That’s something that no other Dog we’ve created can do, and we’d get an error if we tried it.

Max can also bark()—he is a Dog, after all, and inherited that method from the parent class.

But there’s something Max doesn’t have: the coat_patterns property that we defined for our other child class, Catahoula_Dog. Child classes don’t inherit methods or properties from their sibling classes, only from their parent class.

Hopefully those examples are clear! Now: What’s so helpful about parent classes, child classes, and class inheritance in general?

Why Class Inheritance is Useful in OO PHP

With class inheritance, we can convey more meaning, while writing less.

For us as programmers, the advantage of using class inheritance is that we can convey more meaning, while writing less.

When you write inheritance into your OO PHP code, you’re far less likely to need to repeatedly copy-and-paste the same code—and you’re making it possible for people to understand and reuse your structure far better than they would without class inheritance.

Why Class Inheritance is Important: A Commonsense Example

To see this using common sense, let’s examine two possible answers to the question, “What’s a golden retriever?”

  1. A golden retriever is a four-legged mammal, descended from the gray wolf, with social intelligence evolved from pack hunting, domesticated by humans, and kept as a house pet in contemporary societies across the world. There are lots of types of these domesticated-wolf-things, and what makes a golden retriever different from all the other ones is that it has floppy ears and golden fur and likes to fetch.
  2. A golden retriever is a dog with floppy ears and golden fur that likes to fetch.

Do you see how useful it is to be able to say “dog,” or Dog? In OO PHP, you have to write out all the properties and methods that make the Dog parent class special (if you were really coding about dogs in the context of other animals, that’d be public evolved_from_wolves = true; and so on).

Once you’ve done that once, why repeat yourself every time you want to talk about a specific type of dog? That’d be as crazy as example 1 above.

Class inheritance is what lets you not repeat yourself. Just extend Dog, and inherit everything that means—written down once in a centralized place—and then specify what exactly it is about a Golden_Retriever_Dog that’s important to your work.

The Liskov Substitution Principle

You can also be confident that each one of your child classes belongs to something, and has the full set of properties and methods that that belonging requires. In other words, anytime you need a generic Dog for something, you can always send a Golden_Retriever_Dog to do the job, and nothing will break. As simple as this sounds, it’s got an awesome-sounding Russian name: the Liskov substitution principle.

Summing up, class inheritance allows for more code reuse and makes swapping out components easier. That’s good for you right now, and for the people (whether you or others) who read and work with your code in the future.

An Example of Class Inheritance in WordPress: WP_Widget

Once you understand class inheritance, you see it pop up in code pretty often, but I do want to give you one concrete example within WordPress where you simply can’t avoid it: widgets.

The only way to create a new type of widget in WordPress is with code that looks like this:

class WPShout_Custom_Widget extends WP_Widget {}

Why is this? Consider two things:

  1. All WordPress widgets are alike in lots of ways. For example, they all appear in widget areas, and they should all be editable using the drag-and-drop “Widgets” sections of wp-admin and the Customizer.
  2. Despite these similarities, individual WordPress widgets are very different in what they do. Your particular widget could do anything from “feed in my Instagram stories” to “let people sign up for my mailing list.”

This is a perfect use case for class inheritance, and the WordPress core team knocked it out of the park by using OO PHP for the Widgets API. That was by far the best way for them to make the Widgets API behave as it needed to, because they could then:

  1. Create a parent class, WP_Widget, that handles all the properties and methods that all widgets have in common, and
  2. Require individual developers to extend WP_Widget to create their particular widgets’ unique behaviors.

All the details are all in our full course on widgets:

Creating WordPress Widgets: The Complete Guide

If you’ve understood this article and the previous one, learning the Widgets API should be—well, not a breeze (it’s still pretty musty and complicated)—but definitely something that makes general sense.

And That’s the Basics of Class Inheritance in OO PHP

Object orientation is a rich and deep field, and we’re really digging into it. I hope you now understand what topics like “inheritance” and “extending a base class” mean in software, how to write your own parent and child classes in object-oriented PHP, and how to work with class inheritance where it crops up in WordPress development. Thanks for reading!


3 Responses

Pingbacks

Add a Comment

Your email address will not be published. Required fields are marked *