Popular Posts

 How to Inherit from Multiple Objects (Workaround)

As you may know, inheriting from multiple objects in PHP 5 is impossible, because of the language restrictions. You can’t write code such as this:

1
2
3
class Child extends Mother, Father {
	//class code here
}

With a little workaround, eventually we could mimic multi-object inheritance, although it won’t be true multiple inheritance, but it will be pretty close. First let me show you the classic approach of fixing this problem then the new method of inheriting from many objects.

Classic Approach

By stacking up classes and inheriting from each other, it is possible to achieve some sort of inheritance, but this means you sacrifice the manageability and reusability principles of object oriented programming.

The image below illustrates the classic approach.

Object Inheritance Classic Approach

This could be coded in the following way:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class A {
	public function class_a() {
		echo 'this is class a';
	}
}
 
class B extends A {
	public function class_b() {
		echo 'this is class b';
	}
}
 
class C extends B {
	public function class_c() {
		echo 'this is class c';
	}
}
 
class D extends C {
	public function class_d() {
		echo 'this is class d';
	}
}
 
$obj = new D();
 
$obj->class_a();
$obj->class_b();
$obj->class_c();
$obj->class_d();

By implementing this kind of architecture the web project would be doomed from start. Instead let’s have a look at the other approach.

New Method

The idea behind this method is to create an abstract super object which makes it possible to plug-in objects and by instantiating it, all the plugged-in objects’ properties and methods would be available. This is possible with the help of dynamic variable creation.

The classes would be inherited such as the image illustrates below:

Object Inheritance new Method

Dynamic variable creation is a really cool feature in PHP, just as we need to create class properties of classes in our SuperObject class. Let’s build this object creation model. First we create a couple of sample classes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class A {
 
   public function class_a() 
   {
      return 'this is object a';
   }
}
 
class B {
 
   public function class_b() 
   {
      return 'this is object b';
   }
}
 
class C {
 
   public function class_c() 
   {
      return 'this is object c';
   }
}

Then we create the SuperObject class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
abstract class SuperObject 
{
   public function __construct() 
   {
      if (func_num_args() > 0)
      {
         $arr = func_get_args();
 
         for ( $i=0,$m=count($arr); $i<$m; $i++ )
         {
            $class_name = $arr[$i];
 
            $this->extendClass($class_name);
         }			
      }
   }
 
   public function extendClass($class_name)
   {
      $this->$class_name = new $class_name;
   }	
}

The class constructor checks if we passed any class names, if yes then it loops through this array and extends it’s object with these classes. Every class loaded will have a designated dynamic variable in the SuperObject class.

In the extendClass function is where the magic happens. You see the line:

20
$this->$class_name = new $class_name;

Usually we refer to class properties like this:

1
$this->class_prop

But note the extra $ (dollar) sign before the class_name in the extendClass function. This is how dynamic variables are created. The actual dynamic variable name will the value of the passed variable.. For example:

1
2
3
$test = 'hello';
 
$$test = 'world';

Here, $$test name will be the value of the $test, so $hello will be created and it will have the value of $$test which is world. It’s a little hard to understand at first, but once you get the basic idea you’ll find that it’s easy to play with dynamic variables. This same principle applies to our SuperObject. If we load the extendClass function like this:

1
$this->extendClass('A');

Then this function would create a property in the SuperObject like $this->A and it will instantiate the class called A.

As a last step, we need to inherit from the SuperObject class. Let’s create a new class and extend it:

1
2
3
4
5
6
7
class MyObject extends SuperObject
{
   public function __construct()
   {
      parent::__construct('A','B');
   }
}

When we instantiate the MyObject class it will load the A and B classes. Optionally we could load the class C to and plug it in to our object structure.

1
2
$mo = new MyObject();
$mo->extendClass('C');

To access the loaded objects properties and methods, we simply call it from our MyObject instance like this:

1
2
echo $mo->A->class_a();
echo $mo->B->class_b();

Enjoyed this article? Please share it.

Comments
  1. Steven Van Poeck
    December 12th, 2008

    Nice article and well crafted code indeed :)
    Ever seen this: http://en.wikipedia.org/wiki/Diamond_problem? Amongst other drawbacks mentioned here: http://en.wikipedia.org/wiki/Multiple_inheritance#Criticisms

    Personally, for these reasons, I’m glad PHP does not implement multiple inheritance as a language feature. Especially the increased complexity ;) But if I ever really, really, really need multiple inheritance in a PHP code, I’ll come back here…
    Second thought: I’ll probably say to myself that I’ve a misconception somewhere and re-architecture the app ;)

  2. Gyorgy Fekete
    December 12th, 2008

    This method is also can be used when designing a framework for example. This could be the loader class.

    Or when you designing a plug-in architecture like Wordpress.

  3. Bohonyi Balazs - zSolt
    December 13th, 2008

    I’m working as a Java developer (from 9 to 5) and in Java the situation is the same. Multiple inheritance is not allowed, but we can use interfaces to implement multiple inheritance; and I think that this is possible in PHP too:

    interface a { public function foo(); }
    interface b { public function bar(); }

    class c implements a, b {
    public function foo()|{ ............ }
    public function bar() { ............. } }

    You can extend interfaces like classes too. You can even extend class c (from above) from a base class and implement as many interfaces as you want:

    class c extends BaseClass implements a, b {
    public function foo()|{ ............ }
    public function bar() { ............. }

  4. Gyorgy Fekete
    December 13th, 2008

    This is an interesting approach. I will have to look into this in more detail, but from the code you written I think it’s possible.

    Nice job!

  5. Nicolas BUI
    December 14th, 2008

    PHP 5 do not support multiple inheritance and use interfaces instead…
    This is a well-known that multiple inheritance give you a very complex code to maintain… Instead of multiple inheritance, use simply interface or make use of classes composition or maybe using mixing techniques (do rarely use this).

  6. Stelian Mocanita
    December 16th, 2008

    Even though a super object is used in application such as frameworks I do not consider it a best practice. First of all there is the issue of methods overwriting thus getting into the diamond problem and secondly I wouldn’t like to work on my entire API flow with a huge super object that at many points just wastes resources, forcing the compiler to allocate a ton of memory for an object that may only be pointing two or three methods at a time.

    Best practice along me in this case would be making use of the interfaces as that is their main purpose.

  7. Can Berkol
    July 21st, 2009

    Nice article. I needed a sparkle to move on with the application I’m woking on and found it in here. Thanks.

  8. Gyorgy Fekete
    July 21st, 2009

    You’re welcome!

  9. Ignace
    February 23rd, 2010

    echo $mo->A->class_a();
    echo $mo->B->class_b();

    A better approach would be to allow:
    echo $mo->class_a();
    echo $mo->class_b();

    Which can be achieved by using the __call magic method (this of course only works if you assign objects to an internal array instead of to the object properties otherwise you could be checking unnecessary objects for this method) $this->extendClass($class_name); does not check if the class exists.

  10. Gyorgy Fekete
    February 23rd, 2010

    Yes, the __call magic method could be used in this situation.

Leave your reply
  • (required)
  • (will not be published)
  • Show
    ;) :| :virus: :sparta: :ridecursor: :pinkelephant: :love: :linux: :epicfall: :duel: :alien: :P :D :)) :) :( 8O 8)
  • Allowed tags: <a href="" title="">, <b>, <i>, <strike>, <em>, <strong>, <code>