2013-08-13 2 views
0

Отказ от ответственности: то, что вы собираетесь увидеть, является нетрадиционным и может привести к тошноте от средней до тяжелой степени. Держите открытый ум. Так много людей спрашивали о том, как это сделать, и я не думаю, что это обязательно плохое решение.PHP Множественное наследование (цепочка наследования), плагины и производительность

TL; DR - Вы можете спрыгнуть в Grand Finale, если вы знакомы с composition против inheritance и multiple inheritance.

Я читал fewthings, которые предлагают composition лучше, чем inheritance. Я понимаю, что обычно это лучший подход (и я готов использовать композицию, когда это возможно), однако допустим, что я упрямый и хочу попробовать множественное наследование.

То, что я пытаюсь сделать:

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

Что на самом деле работает:

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

Я не против этого, но это не будет работать на более модульный (плагин) подход (скажем, вы не знаете имена классов). Другими словами, если бы я пытался создать структуру OOP, которая позволяла разработчикам расширять базовый класс несколько раз, вам нужно будет входить и редактировать определения классов для расширения B от A, C от B, а затем потенциально переименуйте его обратно в используемый конструктор.

Что я ДЕЙСТВИТЕЛЬНО пытается сделать:

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

Это действительно возможно за счет использования

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

Однако, вы не хотели бы создавать какие-либо фактические код внутри eval, поэтому вы можете использовать временные имена классов.

Grand Finale

См: https://gist.github.com/beeblesox/6218135 (также вставили ниже)

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 

Примечание: Вы не можете просто Eval первую строчку класса (без конца }). Вот почему я использовал временный класс для их переименования.

Идея здесь заключается в том, что будет конечный пустой класс, который пользователь будет иметь как чистый сланец, чтобы добавить свои пользовательские функции. И этот последний класс будет переопределять и наследовать от ядра и любое количество загружаемых плагинов.

Вопросы

Я понимаю, что с 1 или 2 (или 10) дополнительных классов в иерархии (хотя половина из них являются пустыми), не является прекрасной идеей. Однако я не могу себе представить, чтобы производительность была заметна. Может ли средняя загрузка страницы увеличиваться более чем на 1%?

До тех пор, пока нет внешнего (внешнего) ввода, связанного с заявлением eval, вы можете увидеть какие-либо другие последствия?

Чтобы повторить, я прочитал сообщения о композиции. Проблема с композицией и интерфейсами заключается в том, что они не позволяют повторно использовать код. Во многих случаях наследование обеспечивает самый быстрый и чистый способ повторного использования и изменения функциональности без необходимости переписывать что-либо.

ответ

1

Если я правильно понимаю, я думаю, что вы ищете traits, введенный в PHP 5.4.0:

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

Я посмотрел на черты, но я не знаю, если это то, что я хочу использовать в качестве стандартной рабочей процедуры для структуры. –

+0

Разрешить несколько плагинов для расширения основного класса - это то, что я ищу –

+0

Я бы согласился с тем, что черты - это то, что вы ищете. Вы также можете взглянуть на [поведение] Yii (http://www.yiiframework.com/doc/guide/1.1/en/basics.component#component-behavior). Стоит изучить базовый класс ['CComponent'] (https://github.com/yiisoft/yii/blob/master/framework/base/CComponent.php), где они используют магические методы PHP для создания связанных методов поведения и свойства, доступные из класса. –