Risposte:
Non sono d'accordo con la risposta di Chris sotto un aspetto. Le classi Any
, AnyRef
e AnyVal
sono classi. Ma non appaiono come classi in bytecode, a causa delle limitazioni intrinseche della JVM.
Ciò deriva dal fatto che non tutto in Java è un oggetto. Oltre agli oggetti, ci sono primitive. Tutti gli oggetti in Java discendono da java.lang.Object
, ma le primitive sono messe a parte e, attualmente * , non sono estensibili da un programmatore. Nota anche che le primitive hanno "operatori", non metodi.
In Scala, invece, tutto è un oggetto, tutti gli oggetti appartengono a una classe e interagiscono tramite metodi. Il bytecode JVM generato non riflette questo, ma questo non li rende meno, proprio come Java ha generics, anche se il bytecode non li ha.
Quindi, in Scala, tutti gli oggetti discendono da Any
, e questo include sia ciò che Java considera oggetti sia ciò che Java considera primitive. Non esiste un equivalente in Java perché non esiste tale unificazione.
Tutto ciò che è considerato primitivo in Java discende da AnyVal
Scala. Fino a Scala 2.10.0, è AnyVal
stato sigillato ei programmatori non erano in grado di estenderlo. Dovrebbe essere interessante vedere cosa accadrà con Scala su .Net, poiché la sola interoperabilità richiede che Scala riconosca almeno le "primitive" definite dall'utente.
Anche l'estensione Any
è AnyRef
, che è equivalente a java.lang.Object
(sulla JVM in ogni caso).
Fino a Scala 2.9.x, un utente non poteva estendere Any
o AnyVal
, non li riferimento da Java, ma non vi erano altri usi potrebbero essere messi a in Scala. In particolare, le firme del tipo:
def f(x: AnyVal) = println(x)
def g(x: AnyRef) = println(x)
def h(x: Any) = println(x)
Ciò che ciascuno significa dovrebbe essere ovvio dalla gerarchia di classe. Da notare, tuttavia, è che f
e h
verrà auto-box, ma g
non lo farà. Che è un po il contrario di quello che fa Java, in quella f
e h
non può essere specificato, e g
(definito con java.lang.Object
) causerebbe auto-boxing.
A partire da Scala 2.10.0, tuttavia, l'utente può estendere AnyVal
o Any
, con la seguente semantica:
Se una classe si estende AnyVal
, non verrà creata alcuna istanza sull'heap in determinate condizioni. Ciò significa che i campi di questa classe (nella 2.10.0 è consentito solo un singolo campo - resta da vedere se cambierà) rimarranno sullo stack, siano essi primitivi o riferimenti ad altri oggetti. Ciò consente metodi di estensione senza il costo di istanziazione.
Se un tratto si estende Any
, può essere utilizzato sia con le classi che si estendono sia con le classi che si AnyRef
estendono AnyVal
.
PS: Dal mio punto di vista, è probabile che Java segua C # nel consentire primitive "struct" e forse typedef, poiché il parallelismo senza ricorrere ad essi si sta dimostrando difficile da realizzare con buone prestazioni.
Visto? Il testo della pagina ha alcune note di interoperabilità java. http://www.scala-lang.org/node/128
Any
e AnyVal
sono, credo, parte del sistema dei tipi scala e non sono classi in quanto tali (allo stesso modo che Nothing
è un tipo, non una classe). Non è possibile utilizzarli esplicitamente dall'interno del codice Java.
Tuttavia, nell'interoperabilità Java / Scala, un metodo che accetta un Java Object
si aspetterà un scala Any
/ AnyRef
.
Cosa stai effettivamente tentando di fare?
AnyRef
mi hanno ricordato che questo era ancora misterioso per me.
AnyVal
è definito comesealed trait AnyVal extends Any
. Ma in Scala 2.10 questo è cambiato aabstract class AnyVal extends Any with NotNull
, ed ora è possibile estendereAnyVal
con la nuova funzione classi di valore, ad esempio:class MyValue(val u: Int) extends AnyVal
.