Если тип Nothing находится внизу иерархии классов, почему я не могу назвать на нем какой-либо мыслимый метод?
Тип 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)
}
Ответы
Ответ 1
Пока Nothing
является подтипом всего, он не наследует никакого метода, кроме тех, что указаны в Any
. Это связано с тем, что Nothing
больше ориентирован на функциональный конец языка. Это необходимо для таких вещей, как Option
и List
, но только как тип, а не как класс.
Различие здесь немного странно для тех, кто исходит из объектно-ориентированного фона, но факт в том, что подтипирование как понятие очень отличается от ООП. Конечно, объектно-ориентированная на самом деле подразумевает подтипирование в той или иной форме, но обратное неверно. Типы и языки программирования Бенджамина Пирса отлично справляются с представлением языка F_ < (произносится как "F sub" ), который служит минимальным примером язык с подтипированием (но не OO).
Теперь, со всем сказанным, я согласен с тем, что факт, что Nothing
не защищен от нормальных правил наследования, кажется немного несогласованным. Однако, с теоретической точки зрения, это имеет смысл.
Ответ 2
Я полагаю, что Nothing
может принять любой метод и выполнить стандартную операцию над всеми из них (выбрасывая исключение). Это было бы не очень полезно.
Представляя ошибку компиляции, компилятор предупреждает программиста о том, что тип, который он, скорее всего, не хотел, Nothing
, каким-то образом был выведен в определенный момент кода.
Ответ 3
Вы можете вызвать переменную toString
on Nothing
из-за ее дефиниции:
final trait Nothing extends Any
И toString является членом Any
. Я думаю, что scala компилятор обрабатывает Nothing
только в границах типа и рассматривает его как любой другой признак во всех случаях. Думаю, что вызывать любой метод переменной с типом Nothing
будет очень странным.