on Sep 20th, 2008Javascript-OO & Python-DuckTyping in PHP5.3
With the introduction of closures in PHP5.3 my mind has been working a lot trying to find new (ab-)uses for them, first out is a combination of javascript and python oo - honestly this object model is nicer then the standard PHP one.
This allows for changing objects methods during runtime, proper duck-typing, monkey-patching and a lot of other fun stuff only available in javascript/python/ruby normally.
Instance variables, class-variables, etc. it’s all there.
<?php
class MethodException extends Exception {}
class ObjectType {
function __call($name, $args) {
if(isset($this->{$name})) {
array_unshift($args, $this);
return call_user_func_array($this->{$name}, $args);
} else {
throw new MethodException($name);
}
}
}
$obj = function() {
static $say_hi_counter = 0; // Static "class variable" for $obj-type
$self = new ObjectType;
$self->name = null;
$self->say_hi = function($self) use(&$say_hi_counter) {
echo "Hi, my name is: ", $self->name, " ", ++$say_hi_counter, "<br>\n";
};
return $self;
};
$foo = $obj();
$foo->name = "Foo";
$foo->say_hi();
$newobj = function() use($foo) {
$self = clone $foo;
$self->say_goodbye = function($self) {
echo "Goodbye sir<br>\n";
};
return $self;
};
$bar = $newobj();
$bar->say_hi(); // Since $foo is it's "superclass" it will say Foo by default
$bar->name = "Bar";
$bar->say_hi();
$foo->say_hi(); // Still says Foo
$bar->say_goodbye();
$baz = clone $bar; // Create a sibling of bar
$baz->name = "Baz";
$baz->say_hi(); // Baz
$bar->say_hi(); // Stil bar, we changed one of its siblings
/*
Allows for python-style duck-typing
saving failed method calls
*/
try {
$foo->say_goodbye(); // Fails with a "MethodException", $foo doesn't have say_goodbye();
} catch(MethodException $exc) {
echo "Foo can't say goodbye<br>\n";
}