Константы класса 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 это...:-(

Другие вопросы по тегам