Если тип Nothing находится внизу иерархии классов, почему я не могу вызвать для него какой-либо мыслимый метод?

Тип скалы Nothing представляет (насколько я понимаю) дно иерархии типов, также обозначаемое символом ⊥. То есть, Nothing является подтипом любого данного типа. Требование к Nothing Джеймс Айри хорошо объясняет тип для тех из нас, у кого нет теоретических знаний в области теории типов!

Так что мой вопрос, если Nothing является подтипом каждого типа, почему я не могу вызывать методы любого типа на Nothing? Очевидно, я не могу создать экземпляр Nothing, но почему не компилируется следующий код?

var n: Nothing = _

def main(args: Array[String]) {
  println(n.length) //compile error: value length is not a member of Nothing
}

Конечно, как Nothing это подтип String это должно быть хорошо? Обратите внимание, что следующие компиляции просто отлично!

var n: Nothing = _

def foo(s: String) : Int =  s.length

def main(args: Array[String]) {
  println(foo(n))
}

так же как и:

def main(args: Array[String]) {
  println(n.asInstanceOf[String].length) 
}

3 ответа

Решение

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

Различие здесь немного странное для тех, кто приходит из объектно-ориентированного фона, но факт в том, что подтип как концепция очень отличается от ООП. Конечно, объектно-ориентированный действительно подразумевает подтипы в некоторой форме, но обратное неверно. Типы и языки программирования Бенджамина Пирса хорошо представляют язык F_<;; (произносится как "F sub"), который служит минимальным примером языка с подтипами (но не ОО).

Теперь, со всем, что сказал, я согласен, что тот факт, что Nothing иммунитет от нормальных правил наследования кажется немного противоречивым. Однако с теоретической точки зрения это имеет смысл.

Я полагаю Nothing может принять любой метод и выполнить стандартную операцию для всех из них (исключение). Это было бы не очень полезно.

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

Ты можешь позвонить toString на Nothing переменная из-за его определения:
final trait Nothing extends Any
И ToString является членом Any, Я думаю, что Scala компилятор лечить Nothing только в типовых границах и рассматривает это как любую другую черту во всех случаях. Позволяет вызывать любой метод для переменной с типом Nothing будет очень странно, я думаю.

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