note 97181 added to language.oop5.inheritance
| From: | phpatsleepistheenemydotcodotuk at osu1 dot php dot net | Date: | Wed, 07 Apr 2010 09:36:31 +0000 |
| Subject: | note 97181 added to language.oop5.inheritance | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-167745@lists.php.net to get a copy of this message | ||
Here's fun, an attempt to make some degree of multiple inheritance work in PHP using mixins.
It's not particularly pretty, doesn't support method visibility modifiers and, if put to
any meaningful purpose, could well make your call stack balloon to Ruby-on-Rails-esque proportions,
but it does work.
<?php
abstract class Mix {
protected $_mixMap = array();
public function __construct(){
$this->_mixMap = $this->collectMixins($this);
}
public function __call($method, $args){
// doesn't pass scope
//return call_user_func_array(array($className, $method), $args);
// Error: Given object is not an instance of the class this method was declared in
//$method = new ReflectionMethod($className, $method);
//return $method->invokeArgs($this, $args);
$payload = $this->buildMixinPayload($this->_mixMap, $method, $args);
if(!$payload) throw new Exception('Method ' . $method . ' not found');
list($mixinMethod, list($method, $args)) = $payload;
return $this->$mixinMethod($method, $args);
}
protected function collectMixins($class){
static $found = array();
static $branch = array();
if(empty($branch)) $branch[] = get_class($this);
$mixins = array();
foreach(array_reverse(get_class_methods($class)) as $method){
if(preg_match('/^mixin(\w+)$/', $method, $matches)){
$className = $matches[1];
if(in_array($className, $branch))
throw new Exception('Circular reference detected ' . implode('
> ', $branch) . ' > ' . $className);
if(!in_array($className, $found)){
if(!class_exists($className)) throw new Exception('Class ' .
$className . ' not found');
// populate props from mixin class
foreach(get_class_vars($className) as $key => $value){
if(!property_exists($this, $key)) $this->$key = $value;
}
$found[] = $branch[] = $className;
$mixins[$className] = $this->collectMixins($className);
}
$branch = array(get_class($this));
}
}
return $mixins;
}
protected function buildMixinPayload($mixins, $method, $args){
foreach($mixins as $className => $parents){
$mixinMethod = 'mixin' . $className;
if(method_exists($className, $method)) return array($mixinMethod, array($method,
$args));
if(!empty($parents) && $return = $this->buildMixinPayload($parents, $method,
$args)){
return array($mixinMethod, $return);
}
}
return false;
}
}
?>
----
Server IP: 69.147.83.197
Probable Submitter: 81.136.143.29
----
Manual Page -- http://www.php.net/manual/en/language.oop5.inheritance.php
Edit -- https://master.php.net/note/edit/97181
Del: integrated -- https://master.php.net/note/delete/97181/integrated
Del: useless -- https://master.php.net/note/delete/97181/useless
Del: bad code -- https://master.php.net/note/delete/97181/bad+code
Del: spam -- https://master.php.net/note/delete/97181/spam
Del: non-english -- https://master.php.net/note/delete/97181/non-english
Del: in docs -- https://master.php.net/note/delete/97181/in+docs
Del: other reasons-- https://master.php.net/note/delete/97181
Reject -- https://master.php.net/note/reject/97181
Search -- https://master.php.net/manage/user-notes.php