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 EuropeanSwallowe.
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