Черты PHP - определение общих констант
Каков наилучший способ определения констант, которые могут использоваться рядом классов в пространстве имен? Я пытаюсь избежать слишком большого количества наследования, поэтому расширение базовых классов не является идеальным решением, и я изо всех сил пытаюсь найти хорошее решение, используя черты. Возможно ли это каким-либо образом в 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;
Но из-за ограничений черт это невозможно. Есть идеи?
Ответы
Ответ 1
Я закончил тем, что использовал предложенный пользователем интерфейс интерфейсов, так как мне кажется, что это наименее проблемный способ решения этой проблемы. Использование интерфейса для хранения констант, а не контрактов API, имеет неприятный запах, хотя, возможно, эта проблема больше связана с дизайном ОО, чем с реализацией черт.
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;
Ответ 2
Вы также можете использовать статические переменные. Они могут использоваться в классе или самом признаке. - Прекрасно работает для меня в качестве замены для const.
trait myTrait {
static $someVarA = "my specific content";
static $someVarB = "my second specific content";
}
class myCustomClass {
use myTrait;
public function hello()
{
return self::$someVarA;
}
}
Ответ 3
Чтобы ограничить область ваших констант, вы можете определить их внутри пространства имен:
namespace Test;
const Foo = 123;
// generic functions or classes
echo Foo;
echo namespace\Foo;
Недостатком этого подхода является то, что автозагрузка не будет работать для констант, по крайней мере, не для 5.4; типичным способом этого является обертывание этих констант в статическом классе, то есть:
namespace Test;
class Bar
{
const Foo = 123;
}
Ответ 4
Не очень хороший, но может быть...
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();
Ответ 5
Есть немного хакерский способ сделать это, определив константу, а затем вернув эту константу с вашими функциями черты:
define ('myConst','this is a constant');
trait Base {
public function returnConst() {
return myConst;
}
}
class myClass {
use Base;
}
$o = new myClass();
echo $o->returnConst();
Ответ 6
Что-то еще, чтобы рассмотреть, можно ли вместо этого использовать абстрактный класс, а затем наследовать.
abstract class Base
{
const A = 1;
const B = 2;
}
class Class1 extends Base {}
class Class2 extends Base {}
echo Class1::A;
echo Class2::B;
Конечно, часть причин для признаков заключается в замене сложных деревьев наследования композицией. Зависит от ситуации.