Когда Nothing является законным получателем? - PullRequest
0 голосов
/ 26 июня 2018

Будучи подтипом любого другого типа , позволяет гипотетическому типизированному значению Nothing быть переданным любой функции. Однако, хотя такое значение может служить получателем для toString(), оно не может для unary_! (среди прочих).

object Foo {
    def dead(q: Nothing): Unit = {
        println(q);
        q.toString();
        ((b: Boolean) => !b)(q);
        !q; // value unary_! is not a member of Nothing
    }
}

Это ошибка или особенность?

Примечание:

  1. Это Scala-версия эквивалентного вопроса , который я задал на Kotlin .
  2. Работы по реконструкции: !(q.asInstanceOf[Boolean])

Ответы [ 2 ]

0 голосов
/ 26 июня 2018

Вам не нужен апскейтинг. Вам нужно только приписать некоторый тип, который имеет метод unary_!:

def dead(q: Nothing): Unit = {
  !(q: Boolean)
}

Без явного указания типа метод unary_! просто не может быть разрешен, поскольку, хотя Nothing является подтипом из Boolean, это не подкласс из Boolean, поэтому компилятор не может найти метод unary_! в иерархии наследования Nothing.

Тот факт, что вы можете определять такие методы и функции, также не является ошибкой. Ниже приведена полностью допустимая программа, которая использует функцию с типом ввода Nothing для получения совершенно значимого результата 0, без каких-либо ошибок или чего-либо подобного:

def foo[X](xs: List[X], f: (Int, X) => Int) = {
  xs.foldLeft(0)(f)
}

foo(Nil, (i: Int, n: Nothing) => 42)

Наличие Nothing в системе типов - это действительно хорошая идея, потому что это начальный объект (для каждого типа A есть ровно одна функция Nothing => A), и он упрощает многие вещи, потому что это не заставляет вас иметь дело со всеми видами странных угловых случаев.

0 голосов
/ 26 июня 2018

Ничего является подтипом любого другого типа (включая scala.Null); не существует экземпляров этого типа

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

Таким образом, ошибка, если таковая имеется, заключается в том, что компилятор не предупреждает вас о том, что вы создали функцию, которая никогда не может быть вызвана.


В этом случае println(q) работает, потому что Nothing является подтипом Any, а q.toString работает из-за неявного преобразования AnyRef в Object, которое поддерживает toString. Встроенная функция преобразует q в Boolean, что тоже нормально, но Object не поддерживает unary_!, поэтому !q не компилируется.

...