Eu geralmente acabo tentando todas as combinações até compilar. Alguém pode explicar o que devo usar onde?
Eu discordo da resposta de Chris em um aspecto. As classes Any
, AnyRef
e AnyVal
são classes. Mas eles não aparecem como classes no bytecode, devido às limitações intrínsecas da JVM.
Isso decorre do fato de que nem tudo em Java é um objeto. Além de objetos, existem primitivos. Todos os objetos em Java são descendentes de java.lang.Object
, mas os primitivos são separados e, atualmente * , não extensíveis por um programador. Observe também que os primitivos têm "operadores", não métodos.
No Scala, por outro lado, tudo é um objeto, todos os objetos pertencem a uma classe e interagem por meio de métodos. O bytecode da JVM gerado não reflete isso, mas isso não os torna menos, assim como o Java tem genéricos, embora o bytecode não os tenha.
Então, em Scala, todos os objetos são descendentes de Any
, e isso inclui o que Java considera objetos e o que Java considera primitivos. Não há equivalente em Java porque não existe tal unificação.
Tudo o que é considerado primitivo em Java é descendente de AnyVal
Scala. Até o Scala 2.10.0, ele AnyVal
era selado e os programadores não podiam estendê-lo. Deve ser interessante ver o que acontecerá com Scala em .Net, uma vez que a interoperabilidade por si só exige que o Scala reconheça pelo menos "primitivas" definidas pelo usuário.
Também Any
é estendido AnyRef
, que é equivalente a java.lang.Object
(na JVM de qualquer maneira).
Até Scala 2.9.x, um usuário não poderia estender Any
ou AnyVal
, nem fazer referência a eles a partir de Java, mas não foram para outros usos que poderiam ser colocados no Scala. Especificamente, digite assinaturas:
def f(x: AnyVal) = println(x)
def g(x: AnyRef) = println(x)
def h(x: Any) = println(x)
O que cada um significa deve ser óbvio na hierarquia de classes. Digno de nota, no entanto, é que f
e h
irá encaixotar automaticamente, mas g
não irá. Isso é um pouco o oposto do que Java faz, pois f
e h
não pode ser especificado, e g
(definido com java.lang.Object
) causaria caixa automática.
No entanto, a partir do Scala 2.10.0, o usuário pode estender AnyVal
ou Any
, com a seguinte semântica:
Se uma classe estender AnyVal
, nenhuma instância será criada para ela no heap sob certas condições. Isso significa que os campos desta classe (no 2.10.0 apenas um único campo é permitido - se isso vai mudar, resta ver) ficarão na pilha, sejam eles primitivos ou referências a outros objetos. Isso permite métodos de extensão sem o custo de instanciação.
Se uma característica se estende Any
, ela pode ser usada com as classes que se estendem AnyRef
e com as que se estendem AnyVal
.
PS: Na minha opinião, Java provavelmente seguirá o C # ao permitir primitivas "struct" e talvez typedefs, pois o paralelismo sem recorrer a eles está se mostrando difícil de realizar com bom desempenho.
AnyVal
é definido comosealed trait AnyVal extends Any
. Mas no Scala 2.10 isso mudou paraabstract class AnyVal extends Any with NotNull
, e agora é possível estenderAnyVal
com o novo recurso de classes de valor, por exemplo:class MyValue(val u: Int) extends AnyVal
.Visto isso? O texto da página contém alguns comentários sobre interoperabilidade de java. http://www.scala-lang.org/node/128
fonte
Any
eAnyVal
são, creio eu, parte do sistema de tipo scala e não são classes como tais (da mesma forma queNothing
é um tipo, não uma classe). Você não pode usá-los explicitamente de dentro do código Java.No entanto, na interoperação Java / Scala, um método que aceita um Java
Object
espera um scalaAny
/AnyRef
.O que você está realmente tentando fazer?
fonte
AnyRef
apenas me lembrou que isso ainda era misterioso para mim.