rendered paste body<?php
/**
* Класс, реализующий множественное наследование в PHP
* в эксплуатацию не введен, набросок
* @todo Обработка через Reflection видимостей переменных и методов (private, static и т.п.) в __call, __get, __set
*/
class MultipleExtendPattern
{
/**
* Экземпляры унаследованных классов
* @var mixed
*/
private $ExtendsObjects = array();
public function __construct( /** $Class1, ..., $Class2 = array( 'ClassName', 'ConstructorArguments' => array( 'Param1', ..., 'ParamN' ) ), ... */ )
{
# Создаем экзепляры наследуемых классов
foreach( func_get_args() as $Class )
{
if( is_null( $Class ) ) continue;
$ClassName = '';
$ConstructorArguments = array();
if( is_array( $Class ) )
{
$ClassName = array_shift( $Class );
$ConstructorArguments = array_shift( $Class );
}
else $ClassName = $Class;
# Через Reflection создаем экземпляр
$Reflection = new ReflectionClass( $ClassName );
$this->ExtendsObjects[] = call_user_method_array( 'newInstance', $Reflection, &$ConstructorArguments );
}
}
/**
* Перехватываем вызовы методов
* @param string $Method
* @param array $Arguments
* @return mixed
* @todo необходимо ввести правила, определяющие действия при ситуации, когда вызываемый метод находиться в двух и более наследуемых объектах
*/
private function __call( $Method, $Arguments )
{
# Проходимся по всем классам, узнавая у кого есть вызываемый метод
foreach( $this->ExtendsObjects as $Object )
{
if( method_exists( $Object, $Method ) )
{
# Делаем вызов метода
return call_user_method_array( $Method, $Object, &$Arguments );
}
}
}
/**
* Перехватываем обращение к переменным класса
* @param string $VariableName
*/
private function __get( $VariableName )
{
# Проходимся по всем классам, узнавая у кого есть вызываемая переменная
foreach( $this->ExtendsObjects as $Object )
{
if( property_exists( $Object, $VariableName ) )
{
return $Object->{$VariableName};
}
}
}
/**
* Прямое обращение к классам
* @param string $ClassName
* @return mixed
*/
public function getObject( $ClassName )
{
foreach( $this->ExtendsObjects as $Object )
{
if( get_class( $Object ) == $ClassName )
{
return $Object;
}
}
}
}
/**
* Потестируем немного
*/
Class A
{
public $AClassProperty = 'AClassProperty';
static $String;
function __construct( $String = '' )
{
self::$String = $String;
$String = 'AConstructByReference' . PHP_EOL;
}
function AFunction( $String = null )
{
if( is_null( $String ) ) $String = self::$String;
echo 'AFunction: ' . $String . PHP_EOL;
}
}
Class B
{
function BFunction( $String )
{
echo 'BFunction: ' . $String . PHP_EOL;
$String = 'BFunction: BFunctionByReference';
}
}
class AB extends MultipleExtendPattern
{
public function __construct( $AConstructor = array(), $BConstructor = array() )
{
parent::__construct( array( 'A', &$AConstructor ), array( 'B', &$BConstructor ) );
}
}
class ABC extends AB
{
public function __construct( $AConstructor = array(), $BConstructor = array() )
{
parent::__construct( &$AConstructor, &$BConstructor );
}
}
$AString = 'StringA';
$ABC = new ABC( array( &$AString ), array() );
$ABC->AFunction( 'a' );
echo $ABC->AClassProperty;
echo PHP_EOL . $AString;
?>