Michael Lewis
Michael Lewis

Reputation: 4302

PHP Multiple Inheritance (Inheritance Chaining), Plugins, and Performance

Disclaimer: What you're about to see is unconventional and could cause moderate to severe nausea. Keep an open mind. So many people have been asking about how to do this, and I don't think its necessarily a bad solution.

TL;DR - You could jump down to the Grand Finale if you're familiar with composition vs inheritance and multiple inheritance.

I've read a few things that suggest composition is better than inheritance. I understand that its usually a better approach (and I'm committed to using composition when possible), however lets assume that I'm stubborn and want to attempt multiple inheritance.

What I'm trying to do:

class A {}
class B {}
class AB extends A, B {} // doesn't work

What actually works:

class A {}
class B extends A {}
class AB extends B {} // inherits from both A and B

I don't mind this, but it won't work for a more modular (plugin) approach (lets say you don't know the names of the classes). In other words, if I were trying to create an OOP framework that allowed developers to extend a core class multiple times, you'd have to go in and edit the class definitions to extend B from A, C from B, and then potentially rename it back to the usable constructor.

What I'm REALLY trying to do:

class DisplayBase {}
class SomePluginDisplay extends DisplayBase {}
class CrazyPluginDisplay extends SomePluginDisplay {}
// ...
class Display extends {LastPlugin}Display {}

This is actually possible through the use of

eval("class $class_name extends $parent_class_name {}");

However, you wouldn't want to put any actual code inside eval, so you could use temporary class names.

Grand Finale

See: https://gist.github.com/beeblesox/6218135 (also pasted below)

class Base {
    function bse(){ echo "base <br />"; }
}

/* You would have to make a dependency-based loader
 * to keep track of class names.  Here, I'm just hard
* coding to show that it could work...
*/
$parent_class = 'Base';
eval("class _BaseA extends $parent_class {}");
class BaseA extends _BaseA {
    function a(){ echo "a <br />"; }
}

$parent_class = 'BaseA';
eval("class _BaseB extends $parent_class {}");
class BaseB extends _BaseB {
    function b(){ echo "b <br />"; }
}

$parent_class = 'BaseB';
eval("class _End extends $parent_class {}");
class End extends _End {
    function nd(){ echo "end <br />"; }
}

$ab = new End();
$ab->bse(); // base
$ab->a();    // a
$ab->b();    // b
$ab->nd();  // end

Note: You can't just eval the first line of the class (without the end }). This is why I used a temporary class to rename them.

The idea here is that there would be a final, blank class that the user would have as a clean slate to add their custom functionality. And, that final class would override and inherit from the core, and any number of loaded plugins.

Questions

I realize that having 1 or 2 (or 10) extra classes in the hierarchy (even though half of them are blank) isn't a great idea. However, I can't imagine the performance toll would be noticeable. Could the average page load increase by more than 1%?

As long as there is no user (external) input involved with the eval statement, can you see any other consequences?

Just to reiterate, I've read posts about composition. The problem with composition and interfaces, is that they don't allow you to reuse code. In many circumstances, inheritance provides the fastest, cleanest way to reuse and modify functionality without having to rewrite anything.

Upvotes: 0

Views: 269

Answers (1)

elclanrs
elclanrs

Reputation: 94101

If I understand correctly, I think you're looking for traits, introduced in PHP 5.4.0:

trait A {}
trait B {}
class C { use A,B; }

Upvotes: 1

Related Questions