note 97079 added to language.oop5.inheritance
| From: | phpatsleepistheenemydotcodotuk at osu1 dot php dot net | Date: | Wed, 31 Mar 2010 15:39:12 +0000 |
| Subject: | note 97079 added to language.oop5.inheritance | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-167560@lists.php.net to get a copy of this message | ||
Here's fun, a little experiment to get some multiple inheritance working in PHP using mixins, a
mixin class. It's not particularly pretty, doesn't support visibility modifiers and, if
put to any sensible use, could make your call stack balloon to Ruby-on-Railsesque 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: 78.110.173.36
Probable Submitter: 195.234.241.4
----
Manual Page -- http://www.php.net/manual/en/language.oop5.inheritance.php
Edit -- https://master.php.net/note/edit/97079
Del: integrated -- https://master.php.net/note/delete/97079/integrated
Del: useless -- https://master.php.net/note/delete/97079/useless
Del: bad code -- https://master.php.net/note/delete/97079/bad+code
Del: spam -- https://master.php.net/note/delete/97079/spam
Del: non-english -- https://master.php.net/note/delete/97079/non-english
Del: in docs -- https://master.php.net/note/delete/97079/in+docs
Del: other reasons-- https://master.php.net/note/delete/97079
Reject -- https://master.php.net/note/reject/97079
Search -- https://master.php.net/manage/user-notes.php