Se o tipo de nada estiver na parte inferior da hierarquia da classe, por que não posso chamar nenhum método concebível nele?
Pergunta
O tipo scala Nothing
representa (como eu entendo) a parte inferior da hierarquia do tipo, também denotada pelo símbolo ⊥. Aquilo é, Nothing
é um subtipo de qualquer tipo. O requisito para um Nothing
tipo é explicado bem por James Iry Para aqueles de nós sem um contexto teórico da teoria do tipo!
Então minha pergunta é, se Nothing
é um subtipo de todos os tipos, por que não posso chamar os métodos de nenhum tipo Nothing
? Obviamente, não consigo instanciar nada, mas por que o seguinte não compila?
var n: Nothing = _
def main(args: Array[String]) {
println(n.length) //compile error: value length is not a member of Nothing
}
Certamente como Nothing
é um subtipo de String
Isso deve estar bem? Observe que os seguintes compilam bem!
var n: Nothing = _
def foo(s: String) : Int = s.length
def main(args: Array[String]) {
println(foo(n))
}
como faz:
def main(args: Array[String]) {
println(n.asInstanceOf[String].length)
}
Solução
Enquanto Nothing
é um subtipo de tudo, não herdar qualquer método, exceto para aqueles em Any
. Isto é porque Nothing
é mais voltado para o fim funcional do idioma. É necessário para coisas como Option
e List
, mas apenas como um modelo, não como uma classe.
A distinção aqui é um pouco estranha para quem vem de um fundo orientado a objetos, mas o fato é que a subtipagem como conceito é muito distinta do OOP. Concedido, orientado a objetos, realmente implica subtipagem de alguma forma, mas o inverso não é verdadeiro. Benjamin Pierce's Tipos e linguagens de programação faz um bom trabalho de apresentar o idioma F_ (pronunciado "f sub"), que serve como um exemplo mínimo de uma linguagem com subtipagem (mas não OO).
Agora, com tudo isso dito, concordo que o fato de que Nothing
está imune às regras normais de herança parece um pouco inconsistente. No entanto, do ponto de vista teórico, faz todo o sentido.
Outras dicas
Eu suponho Nothing
poderia aceitar qualquer método e executar uma operação padrão em todos eles (lançando uma exceção). Isso não seria muito útil, no entanto.
Ao apresentar um erro de compilação, o compilador está avisando ao programador que um tipo que ele provavelmente não queria, Nothing
, foi inferido de alguma forma em um determinado ponto do código.
Você pode ligar toString
sobre Nothing
variável por causa de sua definição:
final trait Nothing extends Any
E a tostring é membro de Any
. Eu acho que o Scala Compiler Treat Nothing
apenas nos limites do tipo e o trata como qualquer outra característica em todos os casos. Deixar invocar qualquer método em variável com tipo de Nothing
Será muito estranho, eu acho.