Обходной путь для базового синтаксиса, который не анализируется

Я хочу иметь свойство класса, которое позволяет выразить выражение в правой части знака равенства. Все версии PHP дросселируются по следующему коду, но они написаны таким образом, чтобы обеспечить более удобную расширяемость в будущем.

/* Example SDK Class */
class SDK
{
    /* Runtime Option Flags */
    // Strings
    #  0: Makes no change to the strings.
    var $STRING_NONE        = (1 << 0);
    #  1: Removes color codes from the string.
    var $STRING_STRIP_COLOR = (1 << 1);
    #  2: Removes language codes from the string.
    var $STRING_STRIP_LANG  = (1 << 2);
    #  3: Removes all formatting from the string.
    var $STRING_STRIP       = SELF::STRING_STRIP_COLOR & SELF::STRING_STRIP_LANG;
    #  4: Converts color codes to HTML & UTF-8.
    var $STRING_HTML        = (1 << 3);
    #  8: Converts color codes to ECMA-48 escape color codes & UTF-8.
    var $STRING_CONSOLE     = (1 << 4);
    # 16: Changes player names only.
    var $STRING_NAMES       = (1 << 5);
    # 32: Changes host names only.
    var $STRING_HOSTS       = (1 << 6);
    function SDK($fString = SELF::STRING_HTML & SELF::STRING_NAMES & SELF_HOST)
    {
        // constructor code.
    }
}

$SDK &= new SDK(SDK::STRING_NONE);

(1 << 0) кажется мне очень сильным синтаксисом, и не понятно, почему PHP не допустил бы такой вещи. Может ли кто-нибудь подумать о работе, которая будет поддерживать читаемость и будущую расширяемость следующего кода?

Ответ 1

При объявлении константы или свойства класса в PHP вы можете указать только примитивные значения для значений по умолчанию. Так, например, это объявление класса не будет работать:

class TEST {
 const ABC = 2 * 4;
 const DEF = some_function();
 static $GHI = array(
   'key'=> 5 * 3,
 );
}

Но это объявление класса:

class TEST {
 const ABC = 8;
 static $GHI = 15;
}

Эти правила применяются к значениям по умолчанию для констант/свойств класса - вы всегда можете инициализировать другие переменные с результатами выражения:

$a= array(
 'a'=> 1 * 2,
 'b'=> 2 * 2,
 'c'=> 3 * 2,
);

Причиной этого поведения объявления этого класса является следующее: выражения похожи на глаголы. Они что-то делают. Классы похожи на существительные: они что-то объявляют. В декларативном заявлении никогда не должно возникать побочных эффектов заявления о действии. Требование примитивных значений по умолчанию принудительно применяет это правило.

С учетом этого мы можем реорганизовать исходный класс следующим образом:

class SDK
{

    static protected $_types= null;

    static public function getType($type_name) {
        self::_init_types();
        if (array_key_exists($type_name, self::$_types)) {
            return self::$_types[$type_name];
        } else {
            throw new Exception("unknown type $type_name");
        }
    }

    static protected function _init_types() {
        if (!is_array(self::$_types)) {
            self::$_types= array(
                'STRING_NONE'=> 1 << 0,
                // ... rest of the "constants" here
                'STRING_HOSTS'=> 1 << 6
            );
        }
    }

    function __construct($fString = null) {
        if (is_null($fString)) {
            $fString= self::getType('STRING_NONE') & self::getType('STRING_HOSTS');
        }
        var_dump($fString);
    }

}

$SDK &= new SDK(SDK::getType('STRING_HOSTS')); 

Ответ 2

Свойство класса PHP не может иметь выражение в объявлении.

[...] Это объявление может включать инициализацию, но эта инициализация должна быть постоянным значением, то есть она должна быть способна быть оценена во время компиляции, а не должна зависеть от информации о времени выполнения для оценки. [...]

Источник: Руководство PHP: Свойства

Следующий код будет работать нормально, поскольку информация может быть установлена ​​во время компиляции и не требует, чтобы компилятор смотрел где-нибудь еще, какие-либо математические или строковые функции получают информацию.

class goodExample
{
    // These are OK.
    var $Var = 1;
    const consts = 'I\'m a Constant Property of the class goodExample.';
    static $static = array(FALSE, TRUE);
}

С другой стороны, следующее недопустимо, так как значение должно быть проанализировано, чтобы получить истинное значение. Это вообще недействительно в PHP. Для var $Var требуется математическая операция. Для const consts требуется консигноризация и переменная, чтобы получить ее значение, чтобы две причины, по которым этот не работал. Наконец, для свойства static $static требуется еще две математические операции, чтобы получить истинное значение.

class badExample
{
    // These are NOT OK.
    var $Var = 1 + 1;
    const consts = "I'm a constant property of the class " . __CLASS__ . '.';
    static $static = array((1 << 0), (1 << 2));
}

Const & static Ключевые слова

После объявления этих свойств их значение не может измениться.

Const

[...] Константы отличаются от обычных переменных тем, что вы не используете символ $для объявления или используете их.

Значение должно быть константным выражением, а не (например) переменной, свойством, результатом математической операции или вызовом функции.

Также возможно, чтобы интерфейсы имели константы.

Источник: Руководство PHP: Константы класса

static

[...] Объявление свойств класса или методов как статических делает их доступными без необходимости создания экземпляра класса. Свойство, объявленное как статическое, не может быть доступно с помощью экземпляра объекта класса (хотя может использоваться статический метод).

Источник: Руководство по PHP: статическое ключевое слово

static может использоваться вне класса, если вы ссылаетесь на имя класса.

Ответ 3

Я думаю, что ваша проблема только со всеми var, которые у вас есть. Вероятно, они должны быть заменены на const. var был необходим в PHP 4 для объявления переменных-членов, но вызывает ошибку в PHP 5. Вместо этого вы должны использовать const, public и т.д. вместо PHP 5.

Ответ 4

PHP может выполнить (1 << 0), проблема только в том, что вы используете var, когда вы должны использовать const. Кроме того, выполнение self::VARIABLE предназначено для статических переменных, и я считаю, что это должно быть self::$variable (если вы не определяете их как const