Respuestas:
No estaré de acuerdo con la respuesta de Chris en un aspecto. Las clases Any
, AnyRef
y AnyVal
son clases. Pero no aparecen como clases en bytecode, debido a las limitaciones intrínsecas de la JVM.
Esto surge del hecho de que no todo en Java es un objeto. Además de los objetos, hay primitivas. Todos los objetos en Java son descendientes de java.lang.Object
, pero los primitivos están separados y, actualmente * , no son extensibles por un programador. Tenga en cuenta también que las primitivas tienen "operadores", no métodos.
En Scala, por otro lado, todo es un objeto, todos los objetos pertenecen a una clase e interactúan a través de métodos. El código de bytes de JVM generado no refleja esto, pero eso no los hace menos, al igual que Java tiene genéricos, aunque el código de bytes no los tenga.
Entonces, en Scala, todos los objetos son descendientes de Any
, y eso incluye tanto lo que Java considera objetos como lo que Java considera primitivos. No hay equivalente en Java porque no existe tal unificación.
Todo lo que se considera primitivo en Java es descendiente de AnyVal
Scala. Hasta que Scala 2.10.0 AnyVal
se selló y los programadores no pudieron extenderlo. Debería ser interesante ver qué pasará con Scala en .Net, ya que la interoperabilidad por sí sola requiere que Scala reconozca al menos las "primitivas" definidas por el usuario.
Extendiéndose también Any
es AnyRef
, que es equivalente a java.lang.Object
(en la JVM, en cualquier caso).
Hasta Scala 2.9.x, un usuario no puede extender Any
o AnyVal
, ni referencia a ellas desde Java, pero no eran otros usos que se podrían poner en Scala. Específicamente, escriba firmas:
def f(x: AnyVal) = println(x)
def g(x: AnyRef) = println(x)
def h(x: Any) = println(x)
Lo que significa cada uno debería ser obvio a partir de la jerarquía de clases. Sin embargo, es de destacar que f
y h
se auto-box, pero g
no lo hará. Eso es un poco lo contrario de lo que hace de Java, en el que f
y h
no se puede especificar, y g
(definida mediante java.lang.Object
) causaría auto-boxing.
Sin embargo, a partir de Scala 2.10.0, el usuario puede extender AnyVal
o Any
, con la siguiente semántica:
Si una clase se extiende AnyVal
, no se creará ninguna instancia para ella en el montón bajo ciertas condiciones. Esto significa que los campos de esta clase (en 2.10.0 solo se permite un campo único; queda por ver si eso cambiará) permanecerán en la pila, ya sean primitivas o referencias a otros objetos. Esto permite métodos de extensión sin el costo de creación de instancias.
Si un rasgo se extiende Any
, se puede usar tanto con clases que se extienden AnyRef
como con clases que se extienden AnyVal
.
PD: En mi opinión, es probable que Java siga a C # al permitir primitivas de "estructura", y tal vez typedefs, ya que el paralelismo sin recurrir a ellas está resultando difícil de lograr con un buen rendimiento.
¿Visto esto? El texto de la página tiene algunos comentarios de interoperabilidad de Java. http://www.scala-lang.org/node/128
Any
y AnyVal
son, creo, parte del sistema de tipos scala y no son clases como tales (de la misma manera que Nothing
es un tipo, no una clase). No puede utilizarlos explícitamente desde el código Java.
Sin embargo, en la interoperación Java / Scala, un método que acepta un Java Object
esperará un scala Any
/ AnyRef
.
¿Qué estás intentando hacer realmente?
AnyRef
simplemente me recordó que esto todavía era misterioso para mí.
AnyVal
se define comosealed trait AnyVal extends Any
. Pero en Scala 2.10 esto ha cambiado aabstract class AnyVal extends Any with NotNull
, y ahora es posible extenderAnyVal
con la nueva característica de las clases de valor, por ejemplo:class MyValue(val u: Int) extends AnyVal
.