Je finis généralement par essayer chaque combinaison jusqu'à ce qu'elle se compile. Quelqu'un peut-il expliquer ce que je dois utiliser où?
Je ne suis pas d'accord avec la réponse de Chris sur un point. Les classes Any
, AnyRef
et AnyVal
sont des classes. Mais elles n'apparaissent pas comme des classes en bytecode, en raison des limitations intrinsèques de la JVM.
Cela vient du fait que tout en Java n'est pas un objet. En plus des objets, il existe des primitives. Tous les objets en Java sont des descendants de java.lang.Object
, mais les primitives sont mises à part et, actuellement * , non extensibles par un programmeur. Notez également que les primitives ont des "opérateurs", pas des méthodes.
Dans Scala, par contre, tout est un objet, tous les objets appartiennent à une classe et ils interagissent via des méthodes. Le bytecode JVM généré ne reflète pas cela, mais cela ne les rend pas moins, tout comme Java a des génériques, même si le bytecode ne les a pas.
Ainsi, dans Scala, tous les objets sont des descendants de Any
, et cela inclut à la fois ce que Java considère comme des objets et ce que Java considère comme des primitives. Il n'y a pas d'équivalent en Java car une telle unification n'existe pas.
Tout ce qui est considéré comme primitif en Java est un descendant de AnyVal
Scala. Jusqu'à ce que Scala 2.10.0 AnyVal
soit scellé et les programmeurs ne pouvaient pas l'étendre. Il devrait être intéressant de voir ce qui va se passer avec Scala sur .Net, puisque la seule interopérabilité appelle Scala à au moins reconnaître les "primitives" définies par l'utilisateur.
L'extension Any
est également AnyRef
, ce qui équivaut à java.lang.Object
(sur la JVM en tout cas).
Jusqu'à Scala 2.9.x, un utilisateur ne pouvait pas les étendre Any
ou AnyVal
, ni les référencer à partir de Java, mais il y avait d' autres utilisations auxquelles ils pouvaient être utilisés dans Scala. Plus précisément, tapez les signatures:
def f(x: AnyVal) = println(x)
def g(x: AnyRef) = println(x)
def h(x: Any) = println(x)
Ce que chacun signifie devrait être évident à partir de la hiérarchie des classes. Il convient de noter, cependant, est que f
et la h
volonté boîte automatique, mais g
ne sera pas. C'est un peu le contraire de ce que fait Java, en cela f
et h
ne peut pas être spécifié, et g
(défini avec java.lang.Object
) provoquerait un auto-boxing.
À partir de Scala 2.10.0, cependant, l'utilisateur peut étendre AnyVal
ou Any
, avec la sémantique suivante:
Si une classe s'étend AnyVal
, aucune instance ne sera créée pour elle sur le tas sous certaines conditions. Cela signifie que les champs de cette classe (sur 2.10.0, un seul champ est autorisé - il reste à voir si cela changera) resteront sur la pile, qu'il s'agisse de primitives ou de références à d'autres objets. Cela permet des méthodes d'extension sans le coût d'instanciation.
Si un trait s'étend Any
, il peut être utilisé avec les classes qui s'étendent AnyRef
et les classes qui s'étendent AnyVal
.
PS: De mon point de vue, Java est susceptible de suivre C # en autorisant les primitives «struct», et peut-être les typedefs, car le parallélisme sans y recourir s'avère difficile à réaliser avec de bonnes performances.
AnyVal
est définie commesealed trait AnyVal extends Any
. Mais dans Scala 2.10 cela a changé pourabstract class AnyVal extends Any with NotNull
, et il est maintenant possible d'étendreAnyVal
avec les nouvelles classes de valeur caractéristique, par exemple:class MyValue(val u: Int) extends AnyVal
.Vu ca? Le texte de la page contient quelques remarques sur l'interopérabilité Java. http://www.scala-lang.org/node/128
la source
Any
etAnyVal
font, je crois, partie du système de types scala et ne sont pas des classes en tant que telles (de la même manière qu'unNothing
type, pas une classe). Vous ne pouvez pas les utiliser explicitement à partir du code Java.Cependant, dans l'interopérabilité Java / Scala, une méthode qui accepte un Java
Object
attendra un scalaAny
/AnyRef
.Qu'essayez-vous réellement de faire?
la source
AnyRef
me rappelaient que c'était encore mystérieux pour moi.