Created
December 18, 2012 13:02
-
-
Save Integralist/4327823 to your computer and use it in GitHub Desktop.
Refreshing my memory on PHP inheritance and general OOP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Configure error messages | |
ini_set('display_errors',1); | |
error_reporting(E_ALL); | |
class Adult { | |
/* | |
We set the visibility of these properties to 'protected' so they are accessible within the Child class. | |
We prefix private and protected properties/methods with an underscore, so (at a glance) while scanning a long file we can instantly recognise the visibility. | |
*/ | |
protected $_name; | |
protected $_age; | |
/* | |
Note: static properties/methods belong to the whole class (inc. sub classes) | |
To access it from within a class or subclass use `self::` | |
e.g. self::$_teststatic | |
Static properties/methods can also be accessed from outside the class using `ClassName::STATIC` | |
e.g. Adult::$_teststatic | |
Attempts to access a normal public property from outside a class will cause an error, so the `static` keyword is required. | |
You can still set the visibility of a static property/method (e.g. if set to `protected` then running Adult::$_teststatic outside a class would cause an error) | |
*/ | |
public static $_teststatic = 'This is a test static property'; | |
// Indicates how many class instances have been created | |
protected static $_counter = 0; | |
/* | |
Note: this constant can also be accessed from outside the class (like a static property) using `ClassName::CONSTANT` | |
e.g. Adult::LOCATION | |
*/ | |
const LOCATION = 'England'; | |
public function __construct ($name, $age) { | |
$this->_name = $name; | |
$this->_age = $age; | |
$this->introduction(); | |
// Update the static property so we know another new instance has been created | |
self::$_counter++; | |
} | |
public function how_many_instances(){ | |
echo 'There have been: ' . self::$_counter . ' number of class instances created.<hr>'; | |
} | |
public function reset_instances(){ | |
self::$_counter = 0; | |
} | |
public function introduction(){ | |
echo 'Hi, my name is ' . $this->_name . ' and I am ' . $this->_age . ' years old.<hr>'; | |
} | |
// Set visibility to `final` so it can never be modified by a sub class | |
final public function birthday(){ | |
$this->_age++; | |
echo $this->_name . ' has had a birthday and is now ' . $this->_age . ' years old!<hr>'; | |
} | |
} | |
class Child extends Adult { | |
protected $_favtoy; | |
// We've inherited the Constructor from Adult but we'll overwrite it here | |
public function __construct ($name, $age, $favtoy) { | |
// We've not defined these properties (_name & _age) in this class - they're inherited from the Adult class. | |
$this->_name = $name; | |
$this->_age = $age; | |
$this->_favtoy = $favtoy; | |
$this->introduction(); | |
/* | |
Another way to do this with slightly less code is to call the parent class' constructor. | |
One problem I noticed was that if we ran this code we'd need to call the parent constructor AFTER setting properties on this instance (otherwise the property is never set?) | |
I'm not sure why the property would have not set when calling the parent constructor, but for whatever reason it wouldn't work until I moved the call after the properties? | |
*/ | |
//parent::__construct($name, $age); | |
// Update the static property so we know another new instance has been created | |
self::$_counter++; | |
} | |
// We're again, over writing this method so it's different from the Parent class | |
public function introduction(){ | |
echo 'Hi, my name is ' . $this->_name . ' and I am ' . $this->_age . ' years old AND my favourite toy is ' . $this->_favtoy . '.<hr>'; | |
} | |
public function display_location(){ | |
echo self::LOCATION . '<hr>'; // constants defined inside a class need to be references by `SELF::` | |
} | |
} | |
class Baby extends Child { | |
const LOCATION = 'Bedroom'; // Note: constants can't be modified within their own class but sub classes can modify the value | |
/* | |
Note: even though the constant value has been updated if we relied on the inheritance chain then the value displayed would be the one defined in Child class | |
For it to work how we want it to we need to overwrite the `display_location` method completely. | |
We can't use parent::display_location(); inside of the redefined method because the scope/context still changes to the Child class. | |
So we literally need to have a duplicate of the `display_location` method. | |
Really the best thing to do here would be to not use a constant (as it's not actually a constant value if it changes between classes!) | |
Instead we should have used a protected property. | |
*/ | |
public function display_location(){ | |
echo self::LOCATION . '<hr>'; // constants defined inside a class need to be references by `SELF::` | |
} | |
} | |
$dad = new Adult('Bob', 40); | |
$mom = new Adult('Alice', 35); | |
$son = new Child('Jim', 10, 'Rubik Cube'); | |
$baby = new Baby('Katie', 1, 'Thumb'); | |
$dad->birthday(); | |
$son->birthday(); | |
$son->display_location(); | |
$baby->display_location(); | |
echo 'We\'re accessing a public static method: "' . Adult::$_teststatic . '"<hr>'; | |
/* | |
Notice how each class instance references the same static property and returns the same value. | |
This was done on purpose to demonstrate static classes but this example is a bit pointless in real world terms. | |
*/ | |
Adult::how_many_instances(); | |
Child::how_many_instances(); | |
Baby::how_many_instances(); | |
Adult::reset_instances(); // We have effectively set-up a priviledged method (it is public but it can access protected/private data) | |
Adult::how_many_instances(); // So although we can't access the static property directly (as the below line demonstrates) we can still change its value if we really need to. | |
echo Adult::$_counter; // Fatal error: Cannot access protected property Adult::$_counter in /Users/stormcreative/Sites/pdo/Class-inheritance.php on line 137 | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment