Константы класса PHP, кажется, всегда интерпретируются как строки
Константа класса всегда кажется интерпретированной как строка, хотя она определена как целое число. Почему PHP делает такого рода жонглирование типов и как мне это предотвратить?
Смотрите следующий код:
class BitSet {
const NONE = 0;
const FOO = 1;
const BAR = 2;
const ALL = 3;
public function __construct( $flags = self::NONE ) {
if( $flags & self::ALL !== $flags )
throw new \OutOfRangeException( '$flags = '.$flags.' is out of range' );
$this->value = $flags;
}
protected $value = self::NONE;
}
$bs = new BitSet( BitSet::FOO );
Последняя строка (вызов конструктора) выбрасывает OutOfRangeException
:
PHP Fatal error: Uncaught exception 'OutOfRangeException' with message '$flags = 1 is out of range' in test-case.php:12
Stack trace:
#0 /srv/www/matthiasn/class-constant-debug.php(19): BitSet->__construct('1')
#1 {main}
thrown in /srv/www/matthiasn/class-constant-debug.php on line 12
Как вы можете видеть из записи трассировки № 0 константа BitSet::FOO
передается как символ, а не как целое число. Следовательно, операция битовой маски $flags & self::ALL !== $flags
не выполняется для целых чисел, но для побитового представления ASCII и, следовательно, не выполняется.
Что за черт?! Есть ли лучший способ получить это право, чем сделать явный (int)
трансляция везде?
2 ответа
Я не совсем уверен, что вы ожидаете, но учтите, что !==
имеет более высокий приоритет, чем &
так что вы делаете побитовое И между 1
а также true
,
Возможно, вы имеете в виду:
if( ($flags & self::ALL) !== $flags )
Извините, это была моя вина, и я пошел в неправильном направлении. Решение
if( ( $flags & self::ALL ) !== $flags )
добавить скобки. !==
оператор, кажется, имеет более высокий приоритет, чем &
,
Без парантезов, сначала фрагмент self::ALL !== $flags
оценивается в FALSE
а потом $flags & FALSE
оценивается.
PHP это...:-(