Странное поведение - PullRequest
       1

Странное поведение

3 голосов
/ 09 февраля 2012
case class Test(kind: Int) {
  val ifX = if (isX) "is X" else "not X"
  val isX = kind == 1
}

val test = Test(1)
println("ifX=%s, isX=%b".format(test.ifX, test.isX))

Почему этот код печатается: если X = не X, isX = true

Когда передвигается "val ifX" перед "ifX", все в порядке (выведите ifX = is X)

РЕДАКТИРОВАТЬ: Я знаю, как это исправить.Я не могу понять, почему компилятор не выдает предупреждение или ошибку в этой ситуации.

Ответы [ 4 ]

7 голосов
/ 09 февраля 2012

OMG, мне интересно, сколько раз мы пройдем через это ...

Статически невозможно обнаружить неправильно использованные прямые ссылки во всех случаях в чем-то лучше, чем экспоненциальное время.Или, если это так, он достаточно сложен, чтобы никто не делал этого.

Этот конкретный случай достаточно прост - нет наследования, нет расширенных признаков, нет ранних инициализаторов, не вызывается метод, нет замыканий, нет функций, нет ничего.Достаточно просто, что предупреждение может быть добавлено в будущем.

Вы можете поймать его во время выполнения, и Scala предоставляет для этого флаг -Xcheckinit.

Кстати, выможет получить точно такую ​​же проблему в Java, хотя она предупреждает вас в этом конкретном случае.

7 голосов
/ 09 февраля 2012

Как отметил Крис Шейн, isX еще не определено. Я просто хочу добавить, что это не переменная, а значение , что означает, что вы можете сделать его ленивым. Ленивое значение создается только тогда, когда вам это нужно. И ifX, и isX теоретически могут быть ленивыми. Попробуйте что-то вроде этого:

case class Test(kind: Int) {
   val ifX = if (isX) "is X" else "not X"
   lazy val isX = kind == 1
 }

Это должно дать желаемый результат.

7 голосов
/ 09 февраля 2012

Вы предполагаете, что порядок не имеет значения в Scala. Оно делает. Поскольку isX - это значение variable , и хотя оно определяется при запуске ifX, его значение по-прежнему неинициализировано, и поэтому оно является значением по умолчанию для его типа (логическое значение, поэтому false).

Если вы переопределите isX как функцию (def isX = ...), она будет работать.

Это примерно эквивалентно следующей Java:

class Test {
    String ifX;
    bool isX; // Defaults to false, its a primitive after all
    public Test(Int kind) {
        ifX = isX ? "is X" : "not X";
        isX = kind == 1;
    }
}
1 голос
/ 09 февраля 2012

хорошо, isX не определено при первом запуске класса. Вы можете просто переключить обе линии?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...