Подтвердить что ты не робот

Черты 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;

Но из-за ограничений черт это невозможно. Есть идеи?

4b9b3361

Ответ 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;

Конечно, часть причин для признаков заключается в замене сложных деревьев наследования композицией. Зависит от ситуации.