Antworten:
Ich werde Chris ' Antwort in einer Hinsicht nicht zustimmen . Die Klassen Any
, AnyRef
und AnyVal
sind Klassen. Sie werden jedoch aufgrund der inhärenten Einschränkungen der JVM nicht als Klassen im Bytecode angezeigt.
Dies ergibt sich aus der Tatsache, dass nicht alles in Java ein Objekt ist. Neben Objekten gibt es Grundelemente. Alle Objekte in Java stammen von ab java.lang.Object
, aber Grundelemente sind getrennt und derzeit * für einen Programmierer nicht erweiterbar. Beachten Sie auch, dass Grundelemente "Operatoren" und keine Methoden haben.
In Scala, auf der anderen Seite, alles ist ein Objekt, gehören alle Objekte zu einer Klasse, und sie interact durch Methoden. Der generierte JVM-Bytecode spiegelt dies nicht wider, aber das macht sie nicht weniger, genauso wie Java Generika hat, obwohl der Bytecode sie nicht hat.
In Scala stammen also alle Objekte ab Any
, und dazu gehört sowohl, was Java als Objekte betrachtet, als auch was Java als Grundelemente betrachtet. In Java gibt es kein Äquivalent, da es keine solche Vereinheitlichung gibt.
Alles, was in Java als primitiv betrachtet wird, stammt von AnyVal
Scala ab. Bis Scala 2.10.0 AnyVal
versiegelt war und Programmierer es nicht erweitern konnten. Es sollte interessant sein zu sehen, was mit Scala in .Net passieren wird, da die Interoperabilität allein erfordert, dass Scala zumindest benutzerdefinierte "Grundelemente" erkennt.
Ebenfalls erweitert Any
wird AnyRef
, was äquivalent zu java.lang.Object
(auf jeden Fall auf der JVM) ist.
Bis zu Scala 2.9.x konnte ein Benutzer sie nicht von Java aus erweitern Any
oder AnyVal
referenzieren, aber es gab andere Verwendungszwecke, für die sie in Scala verwendet werden konnten. Geben Sie insbesondere Signaturen ein:
def f(x: AnyVal) = println(x)
def g(x: AnyRef) = println(x)
def h(x: Any) = println(x)
Was jedes bedeutet, sollte aus der Klassenhierarchie ersichtlich sein. Bemerkenswert ist jedoch, dass f
und h
wird automatisch boxen, wird aber g
nicht. Das ist ein bisschen das Gegenteil von dem, was Java tut f
und h
was nicht spezifiziert werden kann und g
(definiert mit java.lang.Object
) Auto-Boxing verursachen würde.
Ab Scala 2.10.0 kann der Benutzer jedoch erweitern AnyVal
oder Any
mit der folgenden Semantik:
Wenn eine Klasse erweitert wird AnyVal
, wird unter bestimmten Bedingungen keine Instanz für sie auf dem Heap erstellt. Dies bedeutet, dass die Felder dieser Klasse (in 2.10.0 ist nur ein einziges Feld zulässig - ob sich dies ändert, bleibt abzuwarten) auf dem Stapel verbleiben, unabhängig davon, ob es sich um Grundelemente oder Verweise auf andere Objekte handelt. Dies ermöglicht Erweiterungsmethoden ohne die Instanziierungskosten.
Wenn ein Merkmal erweitert wird Any
, kann es sowohl für erweiterte AnyRef
als auch für erweiterte Klassen verwendet werden AnyVal
.
PS: Meiner Ansicht nach wird Java wahrscheinlich C # folgen, um "struct" -Primitive und möglicherweise typedefs zuzulassen, da sich Parallelität ohne Rückgriff auf sie mit guter Leistung als schwierig herausstellt.
Das gesehen? Der Text der Seite enthält einige Anmerkungen zur Java-Interoperabilität. http://www.scala-lang.org/node/128
Any
und AnyVal
sind, glaube ich, Teil des Scala- Typ-Systems und keine Klassen als solche (genauso wie Nothing
ein Typ, keine Klasse). Sie können sie nicht explizit aus Java-Code heraus verwenden.
Bei der Java / Scala-Interoperation Object
erwartet eine Methode, die Java akzeptiert, jedoch eine Scala Any
/ AnyRef
.
Was versuchst du eigentlich zu tun?
AnyRef
erinnerten mich nur daran, dass dies für mich immer noch mysteriös war.
AnyVal
ist definiert alssealed trait AnyVal extends Any
. In Scala 2.10 hat sich dies jedoch geändertabstract class AnyVal extends Any with NotNull
, und es ist jetzt möglich, esAnyVal
mit der neuen Funktion für Wertklassen zu erweitern , zclass MyValue(val u: Int) extends AnyVal
.