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. |