Chapter 10: Inheritance
In the previous chapter, we covered the fundamentals of OOP. Some of the concepts in OOP can be confusing for beginners. If this is the first time you are exposed to OOP, you may want to read through the previous chapter more than once to fully grasp the concepts.
Once you are comfortable with the topics covered in Chapter 9, we are ready to proceed to a more advanced, but equally important, concept in OOP – inheritance.
As the name suggests, inheritance has to do with the relationship between two or more classes. With inheritance, classes can be declared such that one class is a child class (also known as a subclass) of another (known as the parent class or base class). This enables us to group related classes together.
The easiest way to explain inheritance is to look at an example.
10.1 Writing the Child Classes
We’ll use the Movie
class in Chapter 9 as a parent class to illustrate. Open Brackets and create a new file called AwardWinningMovie.php. Save this file to your htdocs folder.
Add the following code to AwardWinningMovie.php:
<?php
include "Movie.php";
class AwardWinningMovie extends Movie{
private $award;
public function __construct($pId, $pTitle, $pRentalPrice, $pAward){
parent::__construct($pId, $pTitle, $pRentalPrice); $this->award = $pAward;
}
}
In the code above, we first use the include
statement to include the code for the Movie
class. Next, we create a class called AwardWinningMovie
.
Notice a new keyword extends
in the AwardWinningMovie
class declaration? This keyword indicates that AwardWinningMovie
is a child class of Movie
.
When one class is a child class of another, it inherits all the public
and protected
members of the parent class. In other words, it can access and use those members directly, as if they are part of its own code. We’ll illustrate what this means later.
Within the AwardWinningMovie
class, we declare a private
property called $award
. Next, we declare a constructor with 4 parameters, $pId
, $pTitle
, $pRentalPrice
and $pAward
.
Within the constructor, notice a new keyword, parent
?
As you may have guessed, this keyword is used to call the parent class constructor. As the child class has its own constructor, we need to use the parent
keyword and the ::
operator when we want to access the parent class constructor. When we call the parent class constructor, we do not create a new object. Instead, we use the name of the constructor ( __construct()
).
In our example, we pass the values of $pId
, $pTitle
and $pRentalPrice
as arguments to the parent class constructor. These values will be used to initialize the $id
, $title
and $rentalPrice
properties declared in the parent class respectively.
As these properties were declared as private
in the parent class, we are not allowed to access them directly in the child class. Instead, we can only initialize them using the parent class constructor, which is a public
method.
Next, we have the statement
$this->award = $pAward;
This statement is used to initialize the $award
property declared in the child class.
With that, the child class constructor is complete.
Now, let’s add another method to the child class. Add the code below to the AwardWinningMovie
class, after the __construct()
method but before the closing brace of the class:
public function recommend($country){
switch ($this->award){
case 'Best Picture':
$others = 'The Rail';
break;
case 'Best Actor':
$others = '1729';
break;
default:
$others = 'And so it begins';
}
return
'You might also like:<BR>'.
'<BR>Movie Title = '.$others.
'<BR>Rental Price = '.$this->conversion($country);}
Here, we declare a method called recommend()
that has one parameter – $country
. Within the method, we use a switch
statement to assign different values to the local variable $others
, depending on the value of $this->award
.
Next, we return a string recommending a new movie to users. This string should be quite self-explanatory, except for the last part where we use the $this
keyword to call the conversion()
method (refer to the underlined code above) .
Recall that we do not have a conversion()
method in the AwardWinningMovie
class? Will we get an error when we try to call this method?
The answer is no. This is because the AwardWinningMovie
class is a subclass of the Movie
class. Hence, it can access all the public
and protected
members of the parent class directly, as if they are part of its own code.
As the parent class – Movie
– has a public
method called conversion()
, the child class can access this method simply by using the $this
keyword. Got it?
This is one of the main reasons for using inheritance; it allows us to reuse existing code. In our example, the AwardWinningMovie
class can use the conversion()
method directly without having to code it itself.
10.2 Creating a Child Class Object
We are now ready to create a child class object. To do that, create a new file in Brackets and save it as chap10.php to the htdocs folder.
Add the following code to it:
<?php
include 'AwardWinningMovie.php';
$awm = new AwardWinningMovie('A12324', 'Max', 6.99, 'Best Picture');
echo $awm->recommend('Japan');
Here, we first use the include
statement to include the AwardWinningMovie
class.
Next, we use the new
keyword to create an AwardWinningMovie
object, passing 'A12324'
, 'Max'
, 6.99
and 'Best Picture'
as arguments to the constructor.
Finally, after creating the $awm
object, we use it to call the recommend()
method. If you run the code above, you’ll get
You might also like:
Movie Title = The Rail
Rental Price = 768.9
as the output. Straightforward?
10.3 Access Modifiers Revisited
Good! Let’s revisit the concept of access modifiers now.
Previously, we mentioned that when one class extends another, it inherits all the public
and protected
class members of the class it extends. What this means is that it can access those members directly without any restrictions. However, the same does not apply to private
class members. Child classes are not allowed to access private
members of the parent class directly.
To understand what this means, try changing the conversion()
method in the Movie
class to a private
method. In other words, change the line
public function conversion($country)
in Movie.php to
private function conversion($country)
Next, load chap10.php again. What do you get? You get an error message similar to the output below, right?
Fatal error: Uncaught Error: Call to private method Movie::conversion() from context 'AwardWinningMovie'...
This is because when conversion()
is a private
method, we are not allowed to access it directly outside the class in which it is defined (i.e., outside the Movie
class). Hence, the recommend()
method in the AwardWinningMovie
class is not allowed to access it.
Next, change conversion()
to a protected
method and load chap10.php again. Everything works now, right? This is because child classes are allowed to access protected
members in their parent class directly. Hence, the recommend()
method in the AwardWinningMovie
class is now allowed to access the conversion()
method in the Movie
class. Got it? Great!
After changing conversion()
to a protected
method, note that we are only allowed to access it directly inside the class in which it is declared and any subclass that inherits from that class. In other words, we can only access it directly inside the Movie
and AwardWinningMovie
classes.
Recall that previously, we accessed the method in chap9.php? This was all right when conversion()
was a public
method. Now that it is a protected
method, you’ll get an error if you load chap9.php again. If you want to access the conversion()
method in chap9.php directly, you have to change it back to a public
method.
10.4 Overriding
Now that you are familiar with child classes and inheritance, let’s move on to discuss the concept of overriding. Overriding occurs when a child class modifies the methods it inherits from its parent class.
To illustrate what this means, add the following line to chap10.php and load the page.
echo $awm->displayHeading('H1');
You’ll get the text “Award Winning Movies” displayed as a <H1>
heading.
Here, we are calling the displayHeading()
method declared in the parent class. This method is a public
method inherited by the child class. Hence, we can access it using an AwardWinningMovie
object.
Next, let’s see what happens if we code a new version of the displayHeading()
method inside the child class itself. To do that, add the following method to the AwardWinningMovie
class, after the recommend()
method but before the closing brace of the class:
public function displayHeading($tag){
$baseMsg = parent::displayHeading($tag);
return $baseMsg.$this->award;
}
Here, we declare a method with the same name ( displayHeading
) and parameter list ( $tag
) as the method in the parent class. When that happens, we say that the child class method overrides the parent class method.
Within the child class method, we use the parent
keyword to call the parent class displayHeading()
method. Whenever a child class overrides a parent class method, we need to use the parent
keyword (instead of the $this
keyword) if we want to access the parent class method inside the child class.
Next, we assign the result returned by the parent class method to a variable called $baseMsg
. Finally, we concatenate $baseMsg
with the $award
property in the child class and return the result.
If you load chap10.php again, you’ll see the text “Award Winning Movies” displayed as a <H1>
heading, followed by a line that says “Best Picture”. This additional line illustrates that we are now accessing the displayHeading()
method in the child class.
As displayHeading()
has been overridden in the child class, the child class method is called when we access it using a child class object ( $awm
).
If we want to access the displayHeading()
method in the parent class, we have to use a parent class object. For instance, we can do it as follows:
$mv = new Movie('A3244', 'Golden Rose', 3.99);
echo $mv->displayHeading('H1');
If you add the code above to chap10.php and load the page, you’ll only get “Award Winning Movies” (without “Best Picture”) added to the output. This illustrates that $mv
is accessing the displayHeading()
method in the parent class.