274 lines
6.5 KiB
Markdown
274 lines
6.5 KiB
Markdown
|
---
|
|||
|
title: Class Inheritance
|
|||
|
---
|
|||
|
## Class Inheritance
|
|||
|
|
|||
|
_REUSE CODE WITH INHERITANCE IN OBJECT ORIENTED PROGRAMMING_
|
|||
|
|
|||
|
Here, we will talk about how we can re-use code that we wrote without having any code duplication by using inheritance.
|
|||
|
|
|||
|
### Man Class
|
|||
|
|
|||
|
This is our `Man` class:
|
|||
|
|
|||
|
```php
|
|||
|
<?php
|
|||
|
class Man
|
|||
|
{
|
|||
|
// 1. Declare the class variables
|
|||
|
public $name;
|
|||
|
protected $age;
|
|||
|
public $height;
|
|||
|
public $fav_sports;
|
|||
|
private $fav_drinks;
|
|||
|
|
|||
|
// 2. Create a constructor method with 3 required parameters: name, age and height
|
|||
|
public function __construct($name, $age, $height)
|
|||
|
{
|
|||
|
// 2A. Assign the values of parameters to class properties
|
|||
|
// Also known as instance variables
|
|||
|
// Using "$this->property_name"
|
|||
|
$this->name = $name;
|
|||
|
$this->age = $age;
|
|||
|
$this->height = $height;
|
|||
|
|
|||
|
// 2B. Print out the man's attributes and values upon instantiation
|
|||
|
echo "Our man's name is: " . $this->name . "\n";
|
|||
|
echo "He is " . $this->age . " years old and " . $this->height . " tall.";
|
|||
|
}
|
|||
|
|
|||
|
// 3. Create class methods
|
|||
|
public function giveFirmHandshakes()
|
|||
|
{
|
|||
|
return "I give firm handshakes.";
|
|||
|
}
|
|||
|
|
|||
|
public function beStubborn()
|
|||
|
{
|
|||
|
return "I am stubborn.";
|
|||
|
}
|
|||
|
|
|||
|
public function notPutToiletPaper()
|
|||
|
{
|
|||
|
return "It's not humanly possible to remember to put toilet paper rolls when they are finished";
|
|||
|
}
|
|||
|
|
|||
|
// 4. Age getter method
|
|||
|
public function getAge()
|
|||
|
{
|
|||
|
return $this->age;
|
|||
|
}
|
|||
|
|
|||
|
// Age setter method
|
|||
|
public function setAge($age)
|
|||
|
{
|
|||
|
$this->age = $age;
|
|||
|
}
|
|||
|
|
|||
|
// 5. Favorite Drinks setter method
|
|||
|
public function setFavDrinks($drinks = array())
|
|||
|
{
|
|||
|
if ($drinks) {
|
|||
|
$this->fav_drinks = $drinks;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Favorite Drinks getter method
|
|||
|
public function getFavDrinks()
|
|||
|
{
|
|||
|
return $this->fav_drinks;
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
### Healthy Man
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Let’s say we want to create another class called `HealthyMan` which has all the properties and methods of `Man` class.
|
|||
|
|
|||
|
Without having to re-write all the code for `Man` class, we can re-use that code by using the keyword extends.
|
|||
|
|
|||
|
|
|||
|
```php
|
|||
|
<?php
|
|||
|
class HealthyMan extends Man
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
Now we have all the class properties and methods from Man inside `HealthyMan`. We can instantiate `HealthyMan` class to check this real quick.
|
|||
|
|
|||
|
```php
|
|||
|
<?php
|
|||
|
$jackie = new HealthyMan('Jackie', 25, '5\' 5"');
|
|||
|
// => Our man's name is: Jackie
|
|||
|
// => He is 25 years old and 5' 5" tall.
|
|||
|
```
|
|||
|
|
|||
|
We can go ahead and set HealthyMan aka Jackie’s favorite sports and drinks.
|
|||
|
|
|||
|
```php
|
|||
|
<?php
|
|||
|
$jackie->fav_sports = ['swimming', 'weight training'];
|
|||
|
print_r($jackie->fav_sports);
|
|||
|
// =>
|
|||
|
// Array
|
|||
|
// (
|
|||
|
// [0] => swimming
|
|||
|
// [1] => weight training
|
|||
|
// )
|
|||
|
|
|||
|
$jackie->setFavDrinks(['Matcha tea', 'Oolong Tea']);
|
|||
|
print_r($jackie->getFavDrinks());
|
|||
|
// =>
|
|||
|
// Array
|
|||
|
// (
|
|||
|
// [0] => Matcha tea
|
|||
|
// [1] => Oolong Tea
|
|||
|
// )
|
|||
|
```
|
|||
|
|
|||
|
Now let’s see if we can call Man’s class methods like `giveFirmHandshakes()`, `beStubborn()` and `notPutToiletPaper()`.
|
|||
|
|
|||
|
```php
|
|||
|
<?php
|
|||
|
echo "\n" . $jackie->giveFirmHandshakes();
|
|||
|
// => I give firm handshakes.
|
|||
|
|
|||
|
echo "\n" . $jackie->beStubborn();
|
|||
|
// => I am stubborn.
|
|||
|
|
|||
|
echo "\n" . $jackie->notPutToiletPaper();
|
|||
|
// => It's not humanly possible to remember to put toilet paper rolls when they are finished
|
|||
|
```
|
|||
|
|
|||
|
We get all of these by just inheriting Man class using the keyword extends.
|
|||
|
|
|||
|
|
|||
|
### A Real Healthy Man
|
|||
|
|
|||
|
|
|||
|
If we just inherit `HealthyMan` from `Man` class and do nothing with it, then it beats the whole purpose.
|
|||
|
|
|||
|
HealthyMan class has additional properties like `body_fat_percentage` and `workout_per_week`, and methods like `eatHealthy()`, `meditateDaily()` and `laughOften()`.
|
|||
|
|
|||
|
Since these are personal properties, we can either set them visibility of protected or private and create setter/getter methods for the full encapsulation.
|
|||
|
|
|||
|
```php
|
|||
|
<?php
|
|||
|
class HealthyMan extends Man
|
|||
|
{
|
|||
|
/**
|
|||
|
* HealthyMan properties
|
|||
|
*/
|
|||
|
private $body_fat_percentage;
|
|||
|
private $workout_per_week;
|
|||
|
|
|||
|
/**
|
|||
|
* HealthyMan methods
|
|||
|
*/
|
|||
|
public function eatHealthy()
|
|||
|
{
|
|||
|
return "I only eat healthy meals.";
|
|||
|
}
|
|||
|
|
|||
|
public function meditateDaily()
|
|||
|
{
|
|||
|
return "I set aside 20 minutes daily to meditate.";
|
|||
|
}
|
|||
|
|
|||
|
public function laughOften()
|
|||
|
{
|
|||
|
return "I watch funny TV shows to unwind myself.";
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* HealthyMan Setters and Getters
|
|||
|
*/
|
|||
|
public function setBodyFatPercentage($fat_percentage)
|
|||
|
{
|
|||
|
$this->body_fat_percentage = $fat_percentage;
|
|||
|
}
|
|||
|
|
|||
|
public function getBodyFatPercentage()
|
|||
|
{
|
|||
|
return $this->body_fat_percentage;
|
|||
|
}
|
|||
|
|
|||
|
public function setWorkoutPerWeek($workout_times)
|
|||
|
{
|
|||
|
$this->workout_per_week = $workout_times;
|
|||
|
}
|
|||
|
|
|||
|
public function getWorkoutPerWeek()
|
|||
|
{
|
|||
|
return $this->workout_per_week;
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
We can call these methods to see if they are working as expected:
|
|||
|
|
|||
|
```php
|
|||
|
<?php
|
|||
|
|
|||
|
echo "\n" . $jackie->eatHealthy();
|
|||
|
// => I only eat healthy meals.
|
|||
|
|
|||
|
echo "\n" . $jackie->meditateDaily();
|
|||
|
// => I set aside 20 minutes daily to meditate.
|
|||
|
|
|||
|
echo "\n" . $jackie->laughOften();
|
|||
|
// => I watch funny TV shows to unwind myself.
|
|||
|
|
|||
|
$jackie->setBodyFatPercentage(12);
|
|||
|
echo "\nBody Fat %: " . $jackie->getBodyFatPercentage();
|
|||
|
// => Body Fat %: 12
|
|||
|
|
|||
|
$jackie->setWorkoutPerWeek(5);
|
|||
|
echo "\nWorkout Times Per Week: " . $jackie->getWorkoutPerWeek();
|
|||
|
// => Workout Times Per Week: 5
|
|||
|
```
|
|||
|
|
|||
|
We have successfully re-used the existing code and implemented a child class.
|
|||
|
|
|||
|
|
|||
|
### Is He That Stubborn?
|
|||
|
|
|||
|
|
|||
|
Even though he inherited `beStubborn()` from Man class, since Jackie is a healthy man, he is only stubborn only once in a while. We can have Healthy Man’s `beStubborn()` method to say “I am stubborn once in a while” instead of just plain old “I am stubborn” by overriding the parent class’ method.
|
|||
|
|
|||
|
```php
|
|||
|
<?php
|
|||
|
class HealthyMan extends Man
|
|||
|
{
|
|||
|
.....
|
|||
|
.....
|
|||
|
|
|||
|
public function beStubborn()
|
|||
|
{
|
|||
|
return "I am stubborn once in a while.";
|
|||
|
}
|
|||
|
|
|||
|
.....
|
|||
|
.....
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
Now when we can Jackie’s `beStubborn()` method, we will see a different output than before:
|
|||
|
|
|||
|
```php
|
|||
|
<?php
|
|||
|
echo "\n" . $jackie->beStubborn();
|
|||
|
// => I am stubborn once in a while.
|
|||
|
```
|
|||
|
|
|||
|
This demonstrates how method overriding works in OOP.
|
|||
|
|
|||
|
By using method overriding, we are basically re-declaring the parent class’ method inside the child class.
|
|||
|
|
|||
|
This way, any instance of the parent’s class maintains its original method whereas any instance of the child class has the modified or overridden method.
|