Константа класса всегда представляется как строка, хотя она определяется как целое число. Почему 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)
трансляция везде?
Я не совсем уверен, что вы ожидаете, но учтите, что !==
имеет более высокий старшинство чем &
так что вы делаете побитовое И между 1
а также true
,
Возможно, вы имеете в виду:
if( ($flags & self::ALL) !== $flags )
Извините, это была моя вина, и я пошел в неправильном направлении. Решение
if( ( $flags & self::ALL ) !== $flags )
добавить скобки. !==
оператор, кажется, имеет более высокий приоритет, чем &
,
Без парантезов, сначала фрагмент self::ALL !== $flags
оценивается в FALSE
а потом $flags & FALSE
оценивается.
PHP это … 🙁