Отказ от ответственности: то, что вы собираетесь увидеть, является нетрадиционным и может привести к тошноте от средней до тяжелой степени. Держите открытый ум. Так много людей спрашивали о том, как это сделать, и я не думаю, что это обязательно плохое решение.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
, вы можете увидеть какие-либо другие последствия?
Чтобы повторить, я прочитал сообщения о композиции. Проблема с композицией и интерфейсами заключается в том, что они не позволяют повторно использовать код. Во многих случаях наследование обеспечивает самый быстрый и чистый способ повторного использования и изменения функциональности без необходимости переписывать что-либо.
Я посмотрел на черты, но я не знаю, если это то, что я хочу использовать в качестве стандартной рабочей процедуры для структуры. –
Разрешить несколько плагинов для расширения основного класса - это то, что я ищу –
Я бы согласился с тем, что черты - это то, что вы ищете. Вы также можете взглянуть на [поведение] 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 для создания связанных методов поведения и свойства, доступные из класса. –