marek_mar
11-16-2006, 05:30 PM
I had this idea to check if it wouldn't be possible to, somehow, be able to extend a class dynamically. It turns out it is.
I've written two classes that allow you to do this. It is a sort of hack but it works astonishingly well.
To make it work you just have to extend your class by the "dynamic_extend" class and tell it which classes you'd like to have as children.
require 'dynamic_oop.class.php';
class my_extend-able_class extends dynamic_extend
{
protected $property = 'Set by parent';
function __construct()
{
$this->extend('child_class');
$foo = $this->function_in_child_class();
// and so on...
}
}
$c = new my_extend-able_class;
var_dump($c->public_property_in_child_class);
// and so forth...
?>
There is another class, "dynamic_parent" which allows you for this to work both ways.
The class that will become a child of the extend-able class should be extended by it, but it is not required.
class child_class extends dynamic_parent
{
function function_in_child_class()
{
$this->property = 'Set by dynamic child!';
}
}
Calling the parent's elements is only possible after extending it with the dynamic parent.
This hack does have some limitations:
method_exists()/property_exists() will return a wrong value. To overcome this "dynamic_extend" has methods (has_method()/has_property()) that will return the correct answer. Some other functions may give false results as well.
Constants are currently not passed. This can be done though.
Interface will not be inherited. There is no way to fix this though it is not really needed for dynamically added children.
No errors are given even if invalid actions are made (requesting a protected method from outside class for example). This can be arranged :)
The reflection API won't see the child elements. This could be fixed by extending some reflection classes.
Children can't overload anything. This can probably be fixed.
I don't recommend anyone to start using it unless they're sure what they're doing. It's more of nice thing to check out.
Example:
<?php
require 'dynamic_oop.class.php';
$parent = new parent_class();
$parent->extend('child');
//var_dump($parent);
$parent->print_hello();
$parent->foo = ' World';
$parent->print_hello();
//var_dump($parent->bar);
$parent->foo();
print "\n";
var_dump($parent->parent_property);
?>
I've written two classes that allow you to do this. It is a sort of hack but it works astonishingly well.
To make it work you just have to extend your class by the "dynamic_extend" class and tell it which classes you'd like to have as children.
require 'dynamic_oop.class.php';
class my_extend-able_class extends dynamic_extend
{
protected $property = 'Set by parent';
function __construct()
{
$this->extend('child_class');
$foo = $this->function_in_child_class();
// and so on...
}
}
$c = new my_extend-able_class;
var_dump($c->public_property_in_child_class);
// and so forth...
?>
There is another class, "dynamic_parent" which allows you for this to work both ways.
The class that will become a child of the extend-able class should be extended by it, but it is not required.
class child_class extends dynamic_parent
{
function function_in_child_class()
{
$this->property = 'Set by dynamic child!';
}
}
Calling the parent's elements is only possible after extending it with the dynamic parent.
This hack does have some limitations:
method_exists()/property_exists() will return a wrong value. To overcome this "dynamic_extend" has methods (has_method()/has_property()) that will return the correct answer. Some other functions may give false results as well.
Constants are currently not passed. This can be done though.
Interface will not be inherited. There is no way to fix this though it is not really needed for dynamically added children.
No errors are given even if invalid actions are made (requesting a protected method from outside class for example). This can be arranged :)
The reflection API won't see the child elements. This could be fixed by extending some reflection classes.
Children can't overload anything. This can probably be fixed.
I don't recommend anyone to start using it unless they're sure what they're doing. It's more of nice thing to check out.
Example:
<?php
require 'dynamic_oop.class.php';
$parent = new parent_class();
$parent->extend('child');
//var_dump($parent);
$parent->print_hello();
$parent->foo = ' World';
$parent->print_hello();
//var_dump($parent->bar);
$parent->foo();
print "\n";
var_dump($parent->parent_property);
?>