======[PHP] Multi Extends======
Es ist mehr eine Spielerei. Es geht dabei darum, dass man eine Klasse bilden kann, die aus mehr als einer Parent-Klasse abgeleitet ist. Mit Der unten Aufgeführten Klasse 'AbstractMultiExtends' lässt sich dies erstellen
----
{{image class="left" url="images/icons/48/gtk-go-back-rtl.png"}}
=====Ausgangslage=====
----
{{image class="left" url="images/icons/48/application-x-php.png"}}
=====Voraussetzungen=====
Die folgenden Funktionen werden zusätzlich verwendet
[[PhpErrorsAsExceptions]]
[[PhpCreateUserObject]]
[[PhpVarDumpAsHtmlcomment]]
{{image class="left" url="images/icons/48/application-x-php.png"}}
=====Code=====
====Kleines Testspiel====
name = $name; $this->nachname = $nachname;}
static public function gibGeld($betrag){return "{$betrag} Franken"; }
static protected function sagHallo($name){return "Vater sagt 'Hallo {$name}'";}
}
//Klasse Kind. Abgeleitet von Vater und Mutter
//Die Ableitungen werden durch die Abstrakte Klasse AbstractMultiExtends durchgeführt
//Die Parentklassen werden im Constructeur angehängt
//Das simuliert das Verhalten von 'class Kind extends Mutter, Vater{'
class Kind extends AbstractMultiExtends{
public function __construct(){
parent::addExtendedClass('Mutter', 48);
parent::addExtendedClass('Vater', array('Thomas', 'Muster'));
}
public function mutterSagtHallo(){
//Die Funktion sagHallo() ist in beiden Parents definiert. Da Mutter aber zuerst als
//Parent definiert wurde, hat sie vorrang
return $this->sagHallo('Max Muster');
}
public function getName(){
return "Max {$this->nachname}";
}
}
//Test
define('BRNL', "
\n");
$ich = new Kind();
echo $ich->name.BRNL;
echo $ich->gibEssen().BRNL;
echo $ich->gibGeld(10).BRNL;
echo $ich->getName().BRNL;
echo $ich->mutterSagtHallo().BRNL;
echo $ich->nachname;
/* Ausgabe:
Apfel
10 Franken
Max Muster
Mutter sagt 'Hallo Max Muster'
Muster
*/
?>
====AbstractMultiExtends====
objects[$objectName] = create_user_object_array($wrapperClassName, $params);
//Methodennamen der Klasse in einen privaten Array speichern
$this->addItems($objectName, self::C_METHOD, $reflection->getMethods());
//Propertiesnamen der Klasse in einen privaten Array speichern
$this->addItems($objectName, self::C_PROPERTY, $reflection->getProperties());
}
/**
* Methoden oder Properties der Extended-Klasse in den Index einfügen
* @param String $name Objektname
* @param Constante $var Art der items
* @param Array $array Liste der items
*/
final private function addItems($objectName, $list, $items){
//nur items nehmen, die nicht private sind
$items = array_filter($items, create_function('$item', 'return (!$item->isPrivate());'));
//items auf den Namen reduzieren
array_walk($items, create_function('&$item', '$item = $item->name;'));
//Array mit den itemnamen als Key und dem Objektnamen als Value transferieren
$newVars = array_fill_keys($items, "\$this->objects['{$objectName}']");
//items der itemliste hinzufügen.
//Bei Namensgleichheit mit bestehenden wird einer bestehende Zuordnung wird die
//Bestehende beibehalten
$this->$list = array_merge($newVars, $this->$list);
}
/**
* Aufruf einer Methode. Der Aufruf wird an das entsprechende Parentobjekt weitergeleitet
* @param String $name
* @param Array $params
* @return Variant
*/
public function __call($name, $params){
//Prüfen ob die Methode in der Liste der Methoden vorhanden ist
if(array_key_exists($name, $this->methods)){
//dazugehöriges Elternobjekt auslesen
$objectPhp = $this->methods[$name];
$object = eval("return {$objectPhp};");
//Methode im Elternobjekt ausführen
return call_user_func_array(array($object, $name), $params);
}
}
/**
* Aufruf eines Property. Der Aufruf wird an das entsprechende Parentobjekt weitergeleitet
* @param String $name
* @return Variant
*/
public function __get($name){
//Prüfen ob das Property in der Liste der Properties vorhanden ist
if(array_key_exists($name, $this->properties)){
//dazugehöriges Elternobjekt auslesen
$obj = $this->properties[$name];
//Property auslesen
return eval("return {$obj}->{$name};");
}
}
/**
* @param String $className
* @return String
*/
static final private function getObjectName($className){return "obj{$className}";}
/**
* @param String $className
* @return String
*/
static final private function getWrapperName($className){return "{$className}Wrapper";}
/**
* Erstellen einer Wrapperlasse um die ParentClass
* @param String $className
* @return String Name der Wrapperklasse
*/
final private function createWrapperClass(&$reflection){
$className = $reflection->name;
//ReflectionObject der Klasse zur weiteren Analyse anlegen
$wrapperName = self::getWrapperName($className);
$objName = self::getObjectName($wrapperName);
//Die Klasse zusammenstellen
$lines[] =
<<createWrapperMethodes($lines, $reflection);
//Properties hinzufügen
$this->createWrapperProperies($lines, $reflection);
//Klasse schliessen
$lines[] =
<<getMethods() as $method){
if($method->isProtected()){
$params = array();
$modifiers = $method->getModifiers() - ReflectionMethod::IS_PROTECTED + ReflectionMethod::IS_PUBLIC;
$modifiers = implode(' ', Reflection::getModifierNames($modifiers));
foreach($method->getParameters() as $param){
$params[] = $param->getName();
}
array_walk($params, create_function('&$item, $key', '$item = "\${$item}";'));
$paramString = implode(', ', $params);
$lines[] =
<<name}({$paramString}){
return parent::{$method->name}({$paramString});
}
EOT;
}
}
}
/**
* Erstellen der der __get() im Warapper um auf die Potected/Public-Properties der Parentklasse zuzugreiffen
* @param $lines
* @param $reflection
*/
final private function createWrapperProperies(&$lines, ReflectionClass &$reflection){
$properties = array();
foreach($reflection->getProperties() as $property){
if(!$property->isPrivate() && !$property->isStatic()) {
$properties[] = "'{$property->name}'";
}
}
$propertiesS = implode(', ', $properties);
$lines[] =
<<\$name;
}
EOT;
}
}
?>
----
{{image class="left" alt="ico" url="images/icons/48/xfce4-ui.png"}}
=====Kategorien=====
[[CatPhp]] | [[CatLibrary]]