! This post hasn't been updated in over 2 years. The information here might be out of date or obsolete. Use with care!

I wrote yesterday an article introducing Cosmin’s blog. His most recent article is on multiple inheritance and how easy it would be to implement that into weakly typed like PHP. Just have a look at the article.

Having learned OOP in Java, I am generally against multiple inheritance. I believe that if the answer is multiple inheritance, you’re asking the wrong question. But, for “academic” reasons, I tried to implement multiple inheritance in PHP. And I came up with the following abomination.

First, create a parent class from which all classes in need of multiple inheritance extend. The parent classes will be placed in the $_parents array as strings. When the main object is instantiated, the constructor creates objects from all the parent classes. And by using __call() I’m just going to redirect method calls on the main object to the first suitable parent object. I know it sounds complicated, so long story short, just read the code! I’m a developer, not a writer!

/**
 * Abomination class implementing multiple inheritance via
 * __call magic method
 */
abstract class MultipleInheritance
{
    /**
     * List of parent classes
     * 
     * @var array
     * @access protected
     */
    protected $_parents = array();    

    /**
     * List of parent objects - generated automatically
     * 
     * @var array
     * @access private
     */
    private $_parentObjects = array();

    /**
     * Constructor (thank you captain Obvious)
     * 
     * - init the parent objects
     * 
     * @access public
     */
    public function __construct()
    {
        foreach ($this->_parents as $parentClass) {
            $this->_parentObjects []= new $parentClass();
        }
    }

    /**
     * __call magic method
     * 
     * @param string $name 
     * @param array $arguments 
     * @access public
     * @return mixed
     */
    public function __call($name, array $arguments)
    {
        foreach ($this->_parentObjects as $object) {
            if (method_exists($object, $name)) {
                return call_user_func_array(array($object, $name), $arguments);
            }
        }

        throw new Exception('No such method: ' . $name);
    }
}

Now, some very sexist implementations of Mom and Dad classes:

class Dad 
{
    /**
     * Can parallel park
     * 
     * @access public
     * @return void
     */
    public function park()
    {
        echo 'Look, I can parallel park' . PHP_EOL;
    }    

    /**
     * Can ground the kids
     * 
     * @access public
     * @return void
     */
    public function ground()
    {
        echo 'Grounded by DAD' . PHP_EOL;
    }
}

class Mom
{
    protected $_parents = array('GrandMa');

    /**
     * Makes sandwiches
     * 
     * @access public
     * @return void
     */
    public function makeSandwich()
    {
        echo 'Just making a sandwich' . PHP_EOL;
    }    

    /**
     * Can grounds the kids
     * 
     * @access public
     * @return void
     */
    public function ground()
    {
        echo 'Grounded by MOM' . PHP_EOL;
    }
}

…and finally the child class:

class Child extends MultipleInheritance
{
    protected $_parents = array('Dad', 'Mom');
}

Let’s try it out:

$child = new Child();
$child->park();
$child->makeSandwich();
$child->ground();

And it works. And when two parent classes have the same method – ground() in this case – the method belonging to the first encountered class is executed. And voila, multiple inheritance in PHP. Well, sort of.

Now there’s a small problem with the instanceof operator. And by small problem I mean it doesn’t work and there’s no way to fix it. The following code

if ($child instanceof Mom) {
    echo get_class($child) . ' class inherits from Mom' . PHP_EOL; 
} else {
    echo get_class($child) . ' class does not inherit from Mom' . PHP_EOL;
}

will always go on the “else” branch, although in my application’s logic, the Child class extends from the Mom class. And since PHP doesn’t allow overloading the operators, there’s no clean way to do this. Of course, there’s a hacky way around it, by adding an isInstanceOf() method to the MultipleInheritance class:

abstract class MultipleInheritance
{
    // ...
    
    /**
     * Check inheritance
     * 
     * @param string $class 
     * @access public
     * @return bool
     */
    public function isInstanceOf($class)
    {
        if (in_array($this->_parents, $class)) {
            return true;
        }

        foreach ($this->_parentObjects as $parent) {
            if ($parent instanceof MultipleInheritance) {
                if ($parent->isInstanceOf($class)) {
                    return true;
                }
            }
        }

        return false;
    }
}

…and using it to check inheritance:

if ($child->isInstanceOf('Mom')) {
    echo get_class($child) . ' class inherits from Mom' . PHP_EOL; 
} else {
    echo get_class($child) . ' class does not inherit from Mom' . PHP_EOL;
}

But the abomination is not completed yet. Because I used method_exists() instead of is_callable(), magic methods in the parent class will not be detected. To fix this, just change the code from:

if (method_exists($object, $name)) {
    return call_user_func_array(array($object, $name), $arguments);
}

…to…

if (is_callable($object, $name)) {
    return call_user_func_array(array($object, $name), $arguments);
}

…and it will work. At last, the abomination is ready. Doctor Frankenstein would be proud! Here is a gist with the entire example: https://gist.github.com/1652646.

PS: DO NOT USE MULTIPLE INHERITANCE IN REAL LIFE APPLICATIONS!