2011-07-02 13 views
38

W REPL, definiuję funkcję. Zwróć uwagę na typ zwrotu.Scala String vs java.lang.String - typ wnioskowania

scala> def next(i: List[String]) = i.map {"0" + _} ::: i.reverse.map {"1" + _} 
next: (i: List[String])List[java.lang.String] 

A gdybym określić typ zwracanej jako ciąg

scala> def next(i: List[String]): List[String] = i.map {"0" + _} ::: i.reverse.map {"1" + _} 
next: (i: List[String])List[String] 

Dlaczego różnica? Mogę również określić typ zwracany jako List [Any], więc domyślam się, że String jest po prostu nadrzędnym supertype do java.lang.String. Czy będzie to miało jakiekolwiek praktyczne implikacje, czy też nie mogę bezpiecznie określić typu zwrotu?

Odpowiedz

52

To jest bardzo dobre pytanie! Po pierwsze, zapewniam, że możesz bezpiecznie określić typ zwrotu.

Teraz, spójrzmy w to ... tak, kiedy zostawiamy wniosek, Scala podaje java.lang.String, zamiast tylko String. Tak więc, jeśli spojrzysz na "String" w ScalaDoc, nie znajdziesz niczego, co zdaje się wskazywać, że to też nie jest klasa Scala. Musi jednak pochodzić z jakiegoś miejsca.

Zastanówmy się, co Scala domyślnie importuje. Można go znaleźć przez siebie na REPL:

scala> :imports 
1) import java.lang._    (155 types, 160 terms) 
2) import scala._     (801 types, 809 terms) 
3) import scala.Predef._   (16 types, 167 terms, 96 are implicit) 

Pierwsze dwa są pakiety - i rzeczywiście, String można znaleźć na java.lang! Czy to w takim razie? Sprawdźmy, tworząc instancję z tej paczki:

scala> val s: StringBuffer = new StringBuffer 
s: java.lang.StringBuffer = 

scala> val s: String = new String 
s: String = "" 

To chyba nie jest to. Teraz nie może być w pakiecie scala, lub zostałby znaleziony podczas wyszukiwania w ScalaDoc. Zajrzyjmy więc do środka scala.Predef, i oto jest!

type String = String 

Oznacza to String jest ps do java.lang.String (co zostało importowane wcześniej). Że wygląda cyklicznego odniesienia chociaż, ale jeśli sprawdzić source, zobaczysz, że jest określona z pełną ścieżką:

type String  = java.lang.String 

Następnie warto zapytać dlaczego? Cóż, nie mam pojęcia, ale podejrzewam, że tak ważną klasą jest mniej zależna od JVM.

+0

To trochę dziwne, że literały łańcuchowe są uważane za typu java.lang.String, gdy wydaje się, że równie dobrze można wywnioskować, że są typu String. Ale miło wiedzieć, że to dokładnie to samo. –

+0

@Luigi To dlatego, że literały _ są_ typu java.lang.String. Tak naprawdę nie ma tu żadnej konkluzji - są to literały. –

+2

Może najczystsza, najlepsza, dobrze zaplanowana odpowiedź, jaką kiedykolwiek widziałem na SO. Tak odświeżający. Dzięki, Daniel – jbnunn