PHP- Concept of Inheritance

PHP- the concept of Inheritance in OOP is the ability to pass the implementation of the class from parents to children. Yes, classes can have parents, and the technical way of referring to this feature is that a class extends from another class.

When extending a class, we get all the properties and methods that are not defined as private, and the child class can use them as if they were its own. The limitation is that a class can only extend from one parent.

To show an example, let’s consider our Customer class. It contains the properties firstname, surname, email, and id. A customer is actually a specific type of person, one that is registered in our system, so he/she can get books.

But there can be other types of persons in our system, like librarian or guest. And all of them would have some common properties to all people, that is, firstname and surname.

So it would make sense if we create a Person class, and make the Customer class extend from it.

The hierarchic tree would look as follows:

Note how Customer is connected to Person. The methods in Person are not defined in Customer, as they are implicit from the extension. Now save the new class in src/Domain/Person.php, following our convention:

<?php
namespace Bookstore\Domain;
class Person {
 protected $firstname;
 protected $surname;
 public function __construct(string $firstname, string $surname) {
 $this->firstname = $firstname;
 $this->surname = $surname;
 }
 public function getFirstname(): string {
 return $this->firstname;
 }
 public function getSurname(): string {
 return $this->surname;
 }
}
?>

The class defined in the preceding code snippet does not look special; we have just defined two properties, a constructor and two getters. Note though that we defined the properties as protected because if we defined them as private, the children would not be able to access them.

Now we can update our Customer class by removing the duplicate properties and its getters:

<?php
namespace Bookstore\Domain;
class Customer extends Person {
 private static $lastId = 0;
 private $id;
 private $email;
 public function __construct(
 int $id,
 string $name,
 string $surname,
 string $email
 ) {
 if (empty($id)) {
 $this->id = ++self::$lastId;
 } else {
 $this->id = $id;
 if ($id > self::$lastId) {
 self::$lastId = $id;
 }
 }
 $this->name = $name;
 $this->surname = $surname;
 $this->email = $email;
 }
 public static function getLastId(): int {
 return self::$lastId;
 }
 public function getId(): int {
 return $this->id;
 }
 public function getEmail(): string {
 return $this->email;
}
 public function setEmail($email): string {
 $this->email = $email;
 }
}

Note: the new keyword extends; it tells PHP that this class is a child of the Person class. As both Person and Customer are in the same namespace, you do not have to add any use statement..

This code works fine, but we can see that there is a bit of duplication of code. The constructor of the Customer class is doing the same job as the constructor of the Person class.

In order to reference a method or property of the parent class from the child, you can use $this as if the property or method was in the same class.

PHP allows you to redefine a method in the child class that was already present in the parent. If you want to reference the parent’s implementation, you cannot use $this, as PHP will invoke the one in the child.

To force PHP to  use the parent’s method, use the keyword parent:: instead of $this. Update the
constructor of the Customer class as follows:

public function __construct(
 int $id,
 string $firstname,
 string $surname,
 string $email
) {
 parent::__construct($firstname, $surname);
 if (empty($id)) {
 $this->id = ++self::$lastId;
 } else {
 $this->id = $id;
 if ($id > self::$lastId) {
 self::$lastId = $id;
 }
 }
 $this->email = $email;
}

This new constructor does not duplicate code. Instead, it calls the constructor of the parent class Person, sending $firstname and $surname, and letting the parent do what it already knows how to do.

We avoid code duplication and, on top of that, we make it easier for any future changes to be made in the constructor of Person. If we need to change the implementation of the constructor of Person, we will change it in one place only, instead of in all the children.

Leave a Comment

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