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";
}

Trackback URI | Comments RSS

Leave a Reply