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

Тип scala 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 ]

16 голосов
/ 13 ноября 2009

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

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

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

2 голосов
/ 13 ноября 2009

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

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

0 голосов
/ 13 ноября 2009

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

...