Created
January 21, 2012 12:31
-
-
Save motanelu/1652646 to your computer and use it in GitHub Desktop.
Multiple Inheritance in PHP
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 | |
/** | |
* Abomination class implementing multiple inheritance via | |
* __call magic method | |
*/ | |
abstract class MultipleInheritance | |
{ | |
/** | |
* List of parent classes | |
* | |
* @var array | |
* @access protected | |
*/ | |
protected $_parents = array(); | |
/** | |
* List of parent objects - generated automatically | |
* | |
* @var array | |
* @access private | |
*/ | |
private $_parentObjects = array(); | |
/** | |
* Constructor (thank you captain Obvious :) | |
* | |
* - init the parent objects | |
* | |
* @access public | |
*/ | |
public function __construct() | |
{ | |
foreach ($this->_parents as $parentClass) { | |
$this->_parentObjects []= new $parentClass(); | |
} | |
} | |
/** | |
* __call magic method | |
* | |
* @param string $name | |
* @param array $arguments | |
* @access public | |
* @return mixed | |
*/ | |
public function __call($name, array $arguments) | |
{ | |
foreach ($this->_parentObjects as $object) { | |
if (is_callable(array($object, $name))) { | |
return call_user_func_array(array($object, $name), $arguments); | |
} | |
} | |
throw new Exception('No such method: ' . $name); | |
} | |
/** | |
* __set magic method | |
* | |
* @param string $key | |
* @param mixed $value | |
* @access public | |
* @return void | |
*/ | |
public function __set($key, $value) | |
{ | |
foreach ($this->_parentObjects as $object) { | |
// isset() misses null properties | |
if (property_exists($object, $key)) { | |
$object->{$key} = $value; | |
return; | |
} | |
// property_exists() misses magic properties | |
if (isset($object, $key)) { | |
$oject->{$key} = $value; | |
return; | |
} | |
} | |
} | |
/** | |
* __get magic method | |
* | |
* @param string $key | |
* @access public | |
* @return mixed | |
*/ | |
public function __get($key) | |
{ | |
foreach ($this->_parentObjects as $object) { | |
if (property_exists($object, $key) || @$object->{$key}) { | |
return $object->{$key}; | |
} | |
} | |
} | |
/** | |
* Check inheritance | |
* | |
* @param string $class | |
* @access public | |
* @return bool | |
*/ | |
public function isInstanceOf($class) | |
{ | |
if (in_array($class, $this->_parents)) { | |
return true; | |
} | |
foreach ($this->_parentObjects as $parent) { | |
if ($parent instanceof MultipleInheritance) { | |
if ($parent->isInstanceOf($class)) { | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
} | |
/** | |
* Example classes: | |
*/ | |
class Dad | |
{ | |
public $familyName = 'Smith'; | |
/** | |
* Can parallel park | |
* | |
* @access public | |
* @return void | |
*/ | |
public function park() | |
{ | |
echo 'Look, I can parallel park' . PHP_EOL; | |
} | |
/** | |
* Can ground the kids | |
* | |
* @access public | |
* @return void | |
*/ | |
public function ground() | |
{ | |
echo 'Grounded by DAD' . PHP_EOL; | |
} | |
} | |
class GrandMa | |
{ | |
public $familyName = 'Doe'; | |
/** | |
* Knows bed-time stories | |
* | |
* @access public | |
* @return void | |
*/ | |
public function tellStory() | |
{ | |
echo 'When I was your age...' . PHP_EOL; | |
} | |
/** | |
* __isset | |
* | |
* @param string $key | |
* @access public | |
* @return bool | |
*/ | |
public function __isset($key) | |
{ | |
if ($key == 'ancientCraft') { | |
return true; | |
} | |
} | |
/** | |
* __get | |
* | |
* @param string $key | |
* @access public | |
* @return mixed | |
*/ | |
public function __get($key) | |
{ | |
if ($key == 'ancientCraft') { | |
return 'knit'; | |
} | |
} | |
} | |
class Mom extends MultipleInheritance | |
{ | |
protected $_parents = array('GrandMa'); | |
/** | |
* Makes sandwiches | |
* | |
* @access public | |
* @return void | |
*/ | |
public function makeSandwich() | |
{ | |
echo 'Just making a sandwich' . PHP_EOL; | |
} | |
/** | |
* Can grounds the kids | |
* | |
* @access public | |
* @return void | |
*/ | |
public function ground() | |
{ | |
echo 'Grounded by MOM' . PHP_EOL; | |
} | |
} | |
class Child extends MultipleInheritance | |
{ | |
protected $_parents = array('Dad', 'Mom'); | |
} | |
/* | |
Let's try it out: | |
*/ | |
$child = new Child(); | |
$child->park(); // inherited from Dad | |
$child->makeSandwich(); // inherited from Mom | |
$child->ground(); // inherited from both, but the method in the Dad class will execute | |
$child->tellStory(); // inherited from GrandMd | |
if ($child->isInstanceOf('Mom')) { | |
echo get_class($child) . ' class inherits from Mom' . PHP_EOL; | |
} else { | |
echo get_class($child) . ' class does not inherit from Mom' . PHP_EOL; | |
} | |
if ($child->isInstanceOf('GrandMa')) { | |
echo get_class($child) . ' class inherits from GrandMa' . PHP_EOL; | |
} else { | |
echo get_class($child) . ' class does not inherit from GrandMa' . PHP_EOL; | |
} | |
/** | |
* Stranger class | |
*/ | |
class Stranger {} | |
if ($child->isInstanceOf('Stranger')) { | |
echo get_class($child) . ' class inherits from Stranger' . PHP_EOL; | |
} else { | |
echo get_class($child) . ' class does not inherit from Stranger' . PHP_EOL; | |
} | |
echo 'The child\'s family name is ' . $child->familyName . PHP_EOL; | |
if ($child->ancientCraft) { | |
echo 'The child knows to ' . $child->ancientCraft . PHP_EOL; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment