Back to Blog
A
PHP Architect ·

Analysis: Following Ruby Makes PHP Number Two

These days, people sure seem to be coming up with some… interesting names for their projects. Dennis Hotson, for example, wrote in his blog today about PHP Object Oriented Programming Reinvented. That's right—PHPOOPR. Dennis acknowledges that the name needs work. But, getting past that, his blog is about some creative experiments Dennis is working on.  He has come up with a pretty innovative way of creating objects dynamically in PHP that allows for some usage that conventional PHP coding techniques don't support:
  • Classes can be hacked / patched / cloned. Methods can be added to classes at any time.
  • Classes can be scoped. They’re not global, unless you want them to be.
  • Classes can be temporary (and garbage collected).
In Dennis's code, class definitions are objects themselves, created by a base class constructor function Obj().
$class = Obj();
A Factory is a design pattern for an object that can create more objects of various types.  Thus, Obj() is a factory method. The only thing that differentiates one class instance from another is the methods it supports.  You can add new methods to any class by passing a PHP closure to a class object.
$class->fn('new', function ($class) {
  $newClass = Obj($class->methods)
    ->fn('new', function($class) {
      $obj = Obj($class->imethods);
      $args = func_get_args();
      array_shift($args);
      call_user_func_array(array($obj, 'init'), $args);
      return $obj;
    });
  return $newClass;
});
Now, $class can create instances of the respective type, so these class objects are also factories, making Obj() a factory factory.
$object = $class->new();
You can make a class support subclassing by adding a new method to return a new class object, a clone that has the same functions:
$class->fn('extend', function($t) { return clone $t; });
$subclass = $class->extend();
$object = $subclass->new();
Since all classes are factories, extensible classes are therefore also factory factories.  Which makes Obj() a factory factory factory. You can add more methods to each class instance, of course. This is a very clever experiment. But I wonder if Dennis wants to program in the paradigm of everything-is-an-object like Ruby or Python, why doesn't he just use Ruby or Python? His experiment mimics what those languages have already done, but he still has some parts of PHP that developers hate, such as the motley, non-OO built-in functions, and the need for the array() syntax for array literals. There are a number of other features of PHP's conventional OOP that go out the window in Dennis' code:
  • Compile-time typehints: Classes don't even have names, they only have instances, which aren't created until runtime.
  • instanceof: Likewise, you can't test an object's class for its type or any of its supertypes because types don't have names. An object doesn't know what type it is, only what methods it has.
  • Interfaces: Dennis doesn't show how one would force an object to have a certain set of methods to conform to an interface, or how to make any given method have a specified signature.
  • Reflection: PHP's built-in functionality for reporting meta-information about types doesn't work with Dennis' objects, so he'd have to reinvent that wheel.
  • SPL: All the types in SPL rely on conventional class extension and interface implementation, so they're incompatible with Dennis' objects.
  • Autoloading: PHP loads a class automatically if you reference it by its name, but if classes have no name, you have to take responsibility for loading the code that creates classes yourself.
  • ===: The idea of type equivalence is blurred. Two objects are "the same" if they simply have the same set of methods.
  • Code completion: In the same way that an IDE can't infer the methods of an object implemented through the magic method __call(), these dynamic objects have functions that are not known until runtime, so intellisense has no idea what methods exist or what their signatures are.
The experiment Dennis is coding is worthwhile, but not because it will be useful. Instead, it's worthwhile because it illustrates how we rely on the concept of a type in a programming language. Types enforce structure and help us depend on certain assumptions (like the interface of a class), so we can write simpler code. If we have limitless flexibility, we can't rely on any structure remaining in place, so we have to write more complex code to handle an increasing amount of uncertainty and variation. [Updated 09/28@18:52ET to fix the spelling of Dennis' last name (with our apologies)]
A

PHP Architect

September 23, 2010

Share

Our Partners

Collaborating with industry leaders to bring you the best PHP resources and expertise

Interested in partnering? Get in touch →