W Scali wszystkie wartości mają określony typ, włączając w to wartości numeryczne i funkcje. Poniższy diagram ilustruje podzbiór hirarchii typów.
Hierarchia Typów Scali
Typem bazowym dla wszystkich klas jest Any
, jest on też nazywany typem górnym (top type).
Definiuje on uniwersalne metody takie jak equals
, hashCode
oraz toString
.
Any
posiada dwa bezpośrednie podtypy: AnyVal
i AnyRef
.
AnyVal
reprezentuje typy wartości.
Żaden z tych typów nie może przyjąć wartości null
.
Istnieje dziewięć predefiniowanych typów wartości: Double
, Float
, Long
, Int
, Short
, Byte
, Char
, Unit
oraz Boolean
.
Unit
to typ wartości, która nie niesie ze sobą żadnej znaczącej informacji.
Istnieje dokładnie jedna instancja typu Unit
i jest zdefiniowana dosłownie jako: ()
.
Wszystkie funkcje muszą coś zwracać, dlatego w niektórych przypadkach trzeba użyć Unit
do oznaczenia zwracanego typu.
AnyRef
reprezentuje typy referencyjne.
Przez referencje mamy w tym przypadku na myśli wskaźniki do innych obiektów.
Wszystkie typy niebędące wartościami są zdefiniowane jako typy referencyjne.
Każdy typ zdefiniowany przez użytkownika jest podtypem AnyRef
.
Jeżeli Scala użyta jest w kontekście środowiska uruchomieniowego Javy, to AnyRef
odnosi się do java.lang.Object
.
Poniższy przykład pokazuje, że łańcuchy znakowe, liczby całkowite, znaki, wartości logiczne oraz funkcje są obiektami tak samo jak każdy inny obiekt:
val list: List[Any] = List(
"Łancuch znaków",
732, // liczba całkowita
'c', // znak
true, // wartość Boolowska
() => "funkcja anonimowa zwracająca łańcuch znaków"
)
list.foreach(element => println(element))
Program deklaruje wartość list
typu List[Any]
.
Lista jest zainicjowana elementami różnego typu, ale będącymi podtypami scala.Any
- dlatego można je umieścić na tej liście.
Wynik działania powyższego programu:
Łancuch znaków
732
c
true
<function>
Rzutowanie typów
Typy wartości mogą być rzutowane w następujący sposób:
Dla przykładu:
val x: Long = 987654321
val y: Float = x.toFloat // 9.8765434E8 (w tym wypadku tracimy część precyzji)
val face: Char = '☺'
val number: Int = face // 9786
Rzutowanie jest jednokierunkowe, następujący kod nie zadziała:
val x: Long = 987654321
val y: Float = x.toFloat // 9.8765434E8
val z: Long = y // Błąd: Does not conform
Możliwe jest też rzutowanie referencji typu jego podtyp. Zostanie to dokładniej omówione w kolejnych rozdziałach.
Typy Nothing oraz Null
Nothing
jest podtypem wszystkich typów, istnieje na samym dole hierarchii i jest nazywany typem dolnym (bottom type).
Nie istnieje żadna wartość typu Nothing
.
Częstym przykładem użycia jest zasygnalizowanie stanów nieoznaczonych np. wyrzucony wyjątek, wyjście z programu,
nieskończona pętla (ściślej mówiąc - jest to typ wyrażenia które nie ewaluuje na żadną wartość lub metoda, która nie zwraca wyniku).
Null
jest podtypem wszystkich typów referencyjnych (wszystkich podtypów AnyRef
).
Ma pojedynczą wartosć identyfikowaną przez słowo kluczowe null
.
Null
przydaje się głównie do współpracy z innymi językami platformy JVM i nie powinien być praktycznie nigdy używany
w kodzie w jęzku Scala.
W dalszej części przewodnika omówimy alternatywy dla null
.
Contributors to this page:
Contents
- Wprowadzenie
- Podstawy
- Hierarchia typów
- Klasy
- Domyślne wartości parametrów
- Parametry nazwane
- Cechy
- Krotki
- Kompozycja klas przez domieszki
- Funkcje wyższego rzędu
- Funkcje zagnieżdżone
- Rozwijanie funkcji (Currying)
- Klasy przypadków
- Dopasowanie wzorców (Pattern matching)
- Obiekty singleton
- Wzorce wyrażeń regularnych
- Obiekty ekstraktorów
- For Comprehensions
- Klasy generyczne
- Wariancje
- Górne ograniczenia typów
- Dolne ograniczenia typów
- Klasy wewnętrzne
- Typy abstrakcyjne
- Typy złożone
- Jawnie typowane samoreferencje
- Parametry domniemane
- Konwersje niejawne
- Metody polimorficzne
- Lokalna inferencja typów
- Operatory
- Parametry przekazywane według nazwy
- Adnotacje
- Pakiety i importy
- Obiekty pakietu