Jakie są relacje między Any, AnyVal, AnyRef, Object i jak są one mapowane, gdy są używane w kodzie Java?

111

Zwykle próbuję każdej kombinacji, dopóki się nie skompiluje. Czy ktoś może wyjaśnić, czego powinienem użyć, gdzie?

huynhjl
źródło

Odpowiedzi:

125

Pod jednym względem nie zgodzę się z odpowiedzią Chrisa . Klasy Any, AnyRefi AnyVal zajęcia. Ale nie pojawiają się one jako klasy w kodzie bajtowym z powodu wewnętrznych ograniczeń JVM.

Wynika to z faktu, że nie wszystko w Javie jest obiektem. Oprócz obiektów istnieją prymitywy. Wszystkie obiekty w Javie są potomkami java.lang.Object, ale prymitywy są oddzielone i obecnie * nie mogą być rozszerzalne przez programistę. Zauważ również, że prymitywy mają „operatory”, a nie metody.

Z drugiej strony w Scali wszystko jest przedmiotem, wszystkie obiekty należą do klasy i oddziałują za pomocą metod. Wygenerowany kod bajtowy maszyny JVM nie odzwierciedla tego, ale to nie czyni go mniejszym, tak jak Java ma typy generyczne, nawet jeśli kod bajtowy ich nie ma.

Tak więc w Scali wszystkie obiekty są potomkami Any, co obejmuje zarówno to, co Java uważa za obiekty, jak i to, co Java uważa za prymitywy. Nie ma odpowiednika w Javie, ponieważ nie ma takiej unifikacji.

Wszystko, co jest uważane za prymitywne w Javie, pochodzi od AnyValScali. Do wersji 2.10.0 Scala AnyValbyła zapieczętowana i programiści nie mogli jej rozszerzyć. Powinno być interesujące zobaczyć, co się stanie ze Scalą w .Net, ponieważ sama interoperacyjność wymaga od Scali przynajmniej rozpoznawania „prymitywów” zdefiniowanych przez użytkownika.

Rozszerzanie Anyjest również AnyRefrównoznaczne z java.lang.Object(w każdym razie w JVM).

Do Scala 2.9.x, użytkownik nie może wykraczać Anyani AnyVal, ani odwoływać się do nich z Java, ale tam były inne zastosowania mogą one być umieszczone w Scala. W szczególności wpisz podpisy:

def f(x: AnyVal) = println(x)
def g(x: AnyRef) = println(x)
def h(x: Any) = println(x)

To, co każdy oznacza, powinno być oczywiste z hierarchii klas. Warto jednak zauważyć, że jest to fi hbędzie automatyczne, ale gnie będzie. Jest to trochę przeciwieństwo tego, co robi Java, fi hnie można go określić, a g(zdefiniowane za pomocą java.lang.Object) spowodowałoby automatyczne boksowanie.

Począwszy od Scali 2.10.0, użytkownik może jednak rozszerzyć AnyVallub Any, stosując następującą semantykę:

  • Jeśli klasa się rozszerzy AnyVal, w określonych warunkach nie zostanie dla niej utworzona żadna instancja na stercie. Oznacza to, że pola tej klasy (w wersji 2.10.0 dozwolone jest tylko jedno pole - okaże się, czy to się zmieni) pozostaną na stosie, niezależnie od tego, czy są to prymitywy, czy odniesienia do innych obiektów. Umożliwia to stosowanie metod rozszerzających bez ponoszenia kosztów tworzenia instancji.

  • Jeśli cecha się rozszerza Any, może być używana zarówno z klasami, które rozszerzają, jak AnyRefi klasami, które rozszerzają AnyVal.

PS: Moim zdaniem Java prawdopodobnie podąży za C #, zezwalając na prymitywy "struct" i być może typyef, ponieważ paralelizm bez uciekania się do nich okazuje się trudny do osiągnięcia przy dobrej wydajności.

Daniel C. Sobral
źródło
2
Aktualizacja: od Scala 2.9.2 AnyValjest zdefiniowana jako sealed trait AnyVal extends Any. Jednak w Scali 2.10 zmieniło się to na abstract class AnyVal extends Any with NotNulli można teraz rozszerzyć AnyValo nową funkcję klas wartości, np class MyValue(val u: Int) extends AnyVal. : .
ebruchez
@ebruchez Dzięki za notatkę. Zaktualizowałem odpowiedź o omówienie nowych możliwości.
Daniel C. Sobral
Jak ma się do tego nic i nic?
Gaurav Khare,
5

Anyi AnyValsą, jak sądzę, częścią systemu typów scala i nie są klasami jako takimi (w ten sam sposób, że Nothingjest to typ, a nie klasa). Nie można ich używać jawnie z poziomu kodu Java.

Jednak w przypadku współdziałania Java / Scala metoda akceptująca Javę Objectbędzie oczekiwać pliku scala Any/ AnyRef.

Co właściwie próbujesz zrobić?

oxbow_lakes
źródło
Staram się lepiej zrozumieć ten temat, aby wiedzieć, jakiego typu powinienem używać, gdy planuję wywołanie Scala w języku Java lub odwrotnie. Ta odpowiedź stackoverflow.com/questions/2334200/… i jej obsada AnyRefprzypomniała mi, że to wciąż jest dla mnie tajemnicze.
huynhjl