Каков наилучший способ определения констант, которые могут использоваться рядом классов в пространстве имен? Я стараюсь избегать слишком большого наследования, поэтому расширение базовых классов не является идеальным решением, и я изо всех сил пытаюсь найти хорошее решение, используя черты. Является ли это любым возможным способом в PHP 5.4 или должен быть принят другой подход?
У меня есть следующая ситуация:
trait Base { // generic functions } class A { use Base; } class B { use Base; }
Проблема в том, что невозможно определить константы в чертах PHP. В идеале, что бы я хотел, это примерно следующее:
trait Base { const SOME_CONST = 'someconst'; const SOME_OTHER_CONST = 'someotherconst'; // generic functions }
Затем они могут быть доступны, хотя класс, который применяет свойство:
echo A::SOME_CONST; echo B::SOME_OTHER_CONST;
Но из-за ограничений черт это невозможно. Есть идеи? Благодарю.
Я закончил использование @sectus предложений интерфейсов, поскольку он чувствует себя наименее проблематичным способом справиться с этим. Использование интерфейса для хранения констант, а не контрактов API имеет плохой запах, хотя, возможно, эта проблема больше связана с дизайном OO, чем с реализацией признака. Я все еще не очень доволен этим решением, поэтому не буду принимать ответ на некоторое время, если у кого-то есть лучшее предложение.
interface Definition { const SOME_CONST = 'someconst'; const SOME_OTHER_CONST = 'someotherconst'; } trait Base { // generic functions } class A implements Definition { use Base; } class B implements Definition { use Base; }
Это позволяет:
A::SOME_CONST; B::SOME_CONST;
Вы также можете использовать статические переменные. Они могут использоваться в классе или самом признаке. – Прекрасно работает для меня в качестве замены для const.
trait myTrait { static $someVarA = "my specific content"; static $someVarB = "my second specific content"; } class myCustomClass { use myTrait; public function hello() { return self::$someVarA; } }
Чтобы ограничить объем ваших констант, вы можете определить их внутри пространства имен:
namespace Test; const Foo = 123; // generic functions or classes echo Foo; echo namespace\Foo;
Недостатком такого подхода является то, что автозагрузка не будет работать для констант, по крайней мере, не для 5.4; типичным способом этого является обертывание этих констант в статическом классе, то есть:
namespace Test; class Bar { const Foo = 123; }
есть немного хакерский способ сделать это, определив константу, а затем вернув эту константу с вашими характеристическими функциями:
define ('myConst','this is a constant'); trait Base { public function returnConst() { return myConst; } } class myClass { use Base; } $o = new myClass(); echo $o->returnConst();
Что-то еще, чтобы рассмотреть, может ли вы вместо этого использовать абстрактный класс, а затем наследовать.
abstract class Base { const A = 1; const B = 2; } class Class1 extends Base {} class Class2 extends Base {} echo Class1::A; echo Class2::B;
Конечно, часть причин для признаков заключается в замене сложных деревьев наследования композицией. Зависит от ситуации.
Ничего хорошего, но, может быть …
trait Base { public static function SOME_CONST() { return 'value1'; } public static function SOME_OTHER_CONST() { return 'value2'; } // generic functions } class A { use Base; } class B { use Base; } echo A::SOME_CONST(); echo B::SOME_OTHER_CONST();