Dok gornja granica tipa limitira tip na podtip nekog drugog tipa,
donja granica tipa limitira tip da bude nadtip nekog drugog tipa.
Izraz B >: A
izražava tipski parametar B
ili apstraktni tip B
koji je nadtip tipa A
. U većini slučajeva, A
je tipski parametar klase a B
je tipski parametar metode.
Kroz sljedeći primjer vidjećemo zašto je ovo korisno:
trait Node[+B] {
def prepend(elem: B): Node[B]
}
case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {
def prepend(elem: B): ListNode[B] = ListNode(elem, this)
def head: B = h
def tail: Node[B] = t
}
case class Nil[+B]() extends Node[B] {
def prepend(elem: B): ListNode[B] = ListNode(elem, this)
}
Ovaj program implementira jednostruko povezanu listu.
Nil
predstavlja prazan element (tj. prazna lista). class ListNode
je čvor koji sadrži element tipa B
(head
) i referencu na ostatak liste (tail
). Klasa Node
i njeni podtipovi su kovarijantni jer imaju +B
.
Nažalost, ovaj program se ne može kompajlirati jer je parametar elem
u prepend
tipa B
, kojeg smo deklarisali kovarijantnim.
Ovo ne radi jer su funkcije kontravarijantne u svojim tipovima parametara i kovarijantne u svom tipu rezultata.
Da bismo popravili ovo, moramo zamijeniti varijansu tipskog parametra elem
u prepend
.
Ovo radimo uvođenjem novog tipskog parametra U
koji ima B
kao svoju donju granicu tipa.
trait Node[+B] {
def prepend[U >: B](elem: U): Node[U]
}
case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {
def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
def head: B = h
def tail: Node[B] = t
}
case class Nil[+B]() extends Node[B] {
def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
}
Sada možemo uraditi sljedeće:
trait Bird
case class AfricanSwallow() extends Bird
case class EuropeanSwallow() extends Bird
val africanSwallowList= ListNode[AfricanSwallow](AfricanSwallow(), Nil())
val birdList: Node[Bird] = africanSwallowList
birdList.prepend(EuropeanSwallow())
Node[Bird]
može biti dodijeljena africanSwallowList
ali onda prihvatiti EuropeanSwallow
e.
Contributors to this page:
Contents
- Uvod
- Osnove
- Sjedinjeni tipovi
- Klase
- Podrazumijevane vrijednosti parametara
- Imenovani parametri
- Trejtovi
- Tuples
- Kompozicija mixin klasa
- Funkcije višeg reda
- Ugniježdene metode
- Curry-jevanje
- Case klase
- Podudaranje uzoraka (pattern matching)
- Singlton objekti
- Regularni izrazi
- Ekstraktor objekti
- For komprehensije
- Generičke klase
- Varijanse
- Gornja granica tipa
- Donja granica tipa
- Unutarnje klase
- Apstraktni tipovi
- Složeni tipovi
- Self-tipovi
- Implicitni parametri
- Implicitne konverzije
- Polimorfne metode
- Lokalno zaključivanje tipova (type inference)
- Operatori
- By-name parametri
- Anotacije
- Packages and Imports
- Package Objects