Varijansa je korelacija podtipskih veza kompleksnih tipova i podtipskih veza njihovih tipova komponenti. Scala podržava anotacije varijanse tipskih parametara generičkih klasa, dozvoljavajući im da budu kovarijantni, kontravarijantni, ili invarijantni ako se anotacije ne koriste. Korištenje varijanse u sistemu tipova dozvoljava pravljenje intuitivnijih veza među kompleksnim tipovima, a nedostatak varijanse može ograničiti ponovno iskorištenje klasne apstrakcije.
class Foo[+A] // kovarijantna klasa
class Bar[-A] // kontravarijantna klasa
class Baz[A]  // invarijantna klasa
Kovarijansa
Tipski parametar A generičke klase može se učiniti kovarijantnim koristeći anotaciju +A. 
Za neku klasu List[+A], praveći A kovarijantnim implicira da za dva tipa A i B gdje je A podtip od B, onda je List[A] podtip od List[B]. 
Ovo dozvoljava pravljenje vrlo intuitivnih podtipskih veza koristeći generiku.
Razmotrite sljedeću strukturu klasa:
abstract class Animal {
  def name: String
}
case class Cat(name: String) extends Animal
case class Dog(name: String) extends Animal
Oboje Cat i Dog su podtipovi od Animal. 
Scalina standardna biblioteka sadrži generičk nepromjenjivu sealed abstract class List[+A] klasu, gdje je tipski parametar A kovarijantan.
Ovo znači da je List[Cat] također i List[Animal], a List[Dog] je isto List[Animal]. 
Intuitivno, ima smisla da su lista mačaka i lista pasa također liste životinja, i trebalo bi da možete zamijeniti bilo koju od njih za List[Animal].
U sljedećem primjeru, metoda printAnimalNames prima listu životinja kao argument i ispisuje njihova imena, svako na idućoj liniji. 
Da List[A] nije kovarijantna, zadnja dva poziva metode se ne bi kompajlirali, što bi značajno ograničilo korisnost printAnimalNames metode.
object CovarianceTest extends App {
  def printAnimalNames(animals: List[Animal]): Unit = {
    animals.foreach { animal =>
      println(animal.name)
    }
  }
  val cats: List[Cat] = List(Cat("Whiskers"), Cat("Tom"))
  val dogs: List[Dog] = List(Dog("Fido"), Dog("Rex"))
  printAnimalNames(cats)
  // Whiskers
  // Tom
  printAnimalNames(dogs)
  // Fido
  // Rex
}
Kontravarijansa
Tipski parametar A generičke klase može se učiniti kontravarijantnim koristeći anotaciju -A. 
Ovo kreira podtipsku vezu između klase i njenih tipskih parametara koja je suprotna od kovarijanse.
To jest, za neku class Writer[-A], kontravarijantno A znači da za dva tipa A i B gdje je A podtip B, Writer[B] je podtip Writer[A].
Razmotrimo Cat, Dog, i Animal klase u sljedećem primjeru:
abstract class Printer[-A] {
  def print(value: A): Unit
}
Printer[A] je jednostavna klasa koja zna ispisati neki tip A. Definišimo neke podklase za specifične tipove:
class AnimalPrinter extends Printer[Animal] {
  def print(animal: Animal): Unit =
    println("The animal's name is: " + animal.name)
}
class CatPrinter extends Printer[Cat] {
  def print(cat: Cat): Unit =
    println("The cat's name is: " + cat.name)
}
Ako Printer[Cat] zna kako da ispiše bilo koju Cat, a Printer[Animal] zna kako da ispiše bilo koju Animal, 
ima smisla da Printer[Animal] također zna ispisati Cat. 
Inverzna veza ne vrijedi, jer Printer[Cat] ne zna kako da ispiše bilo koju Animal. 
Stoga, terbali bismo moći zamijeniti Printer[Animal] za Printer[Cat], ako želimo, i praveći Printer[A] kontravarijantnim nam to dozvoljava.
object ContravarianceTest extends App {
  val myCat: Cat = Cat("Boots")
  def printMyCat(printer: Printer[Cat]): Unit = {
    printer.print(myCat)
  }
  val catPrinter: Printer[Cat] = new CatPrinter
  val animalPrinter: Printer[Animal] = new AnimalPrinter
  printMyCat(catPrinter)
  printMyCat(animalPrinter)
}
Izlaz programa biće:
The cat's name is: Boots
The animal's name is: Boots
Invarijansa
Generičke klase u Scali su invarijantne po defaultu. 
Ovo znač da nisu ni kovarijantne ni kontravarijantne. 
U kontekstu sljedećeg primjera, Container klasa je invarijantna. 
Container[Cat] nije Container[Animal], niti obrnuto.
class Container[A](value: A) {
  private var _value: A = value
  def getValue: A = _value
  def setValue(value: A): Unit = {
    _value = value
  }
}
Čini se prirodnim da bi Container[Cat] trebao biti također Container[Animal], ali dozvoljavanjem promjenjivoj generičkoj klasi da bude kovarijantna ne bi bilo sigurno. 
U ovom primjeru, vrlo važno je da je Container invarijantan. 
Pretpostavimo da je Container kovarijantan, nešto slično bi se moglo desiti:
val catContainer: Container[Cat] = new Container(Cat("Felix"))
val animalContainer: Container[Animal] = catContainer
animalContainer.setValue(Dog("Spot"))
val cat: Cat = catContainer.getValue // Ups, završili smo dodjeljivanjem Dog u Cat
Srećom, kompajler nas sprečava davno prije nego dođemo do ovoga.
Drugi primjeri
Još jedan primjer koji može pomoći za shvatanje varijanse je trait Function1[-T, +R] iz Scaline standardne biblioteke. 
Function1 predstavlja funkciju s jednim argumentom, gdje prvi tipski parametar T predstavlja tip argument, 
a drugi parametar R predstavlja povratni tip. 
Function1 je kontravarijantna u tipu argumenta, i kovarijantna u povratnom tipu.
Za ovaj primjer koristićemo literal notaciju A => B za predstavljanje Function1[A, B].
Pretpostavimo da imamo sličnu hijerarhiju klasa Cat, Dog, Animal otprije, plus sljedeće:
class SmallAnimal
class Mouse extends SmallAnimal
Recimo da radimo sa funkcijama koje primaju tipove životinja, i vraćaju tipove hrane koju jedu.
Ako bismo htjeli funkciju Cat => SmallAnimal (jer mačke jedu male životinje), ali nam je data Animal => Mouse funkcija, 
naš program će i dalje raditi. 
Intuitivno Animal => Mouse će i dalje prihvatiti Cat kao argument, jer Cat jeste Animal, i vraća Mouse, koji je također SmallAnimal. 
Pošto sigurno i nevidljivo možemo zamijeniti prvo drugim, možemo reći da je Animal => Mouse podtip Cat => SmallAnimal.
Uporedba s drugim jezicima
Varijansa je podržana na različite načine u nekim drugim jezicima sličnim Scali. Npr, anotacije varijanse u Scali podsjećaju na one u C#, gdje se anotacije dodaju pri deklaraciji klasne apstrakcije (varijansa na strani deklaracije). U Javi, međutim, anotacije varijanse daju korisnici kada se klasna apstrakcija koristi (varijansa na strani korisnika).
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