Scala 変位指定
2019-02-25 (Mon) · 231 words

https://speakerdeck.com/taketora/bian-wei-zhi-ding-nituitewakariyasukujie-shuo-sasetekudasai-a9b35ffb-c910-493e-a9f0-de09f6487918?slide=32

Scala型パラメータ

はじめに

例) クラス定義時に何の型が入るか不明であるため、型引数としてTを定義

class Glass[T](var content: T) {
  def put(t: T): Unit = { content = t }
  def get: T = content
}

型を定義する

class Drink
class Juice extends Drink
class Water extends Drink

インスタンス化するときに、型を決定する

val waterGlass = new Glass[Water](new Water)
val juiceGlass = new Glass[Juice](new Juice)

サブタイプ

例)

val drink: Drink = new Juice

非変

// コンパイルエラー
val glassDrink: Glass[Drink] = new Glass[Water](new Water)

これを非変といい、Scalaではデフォルト

共変

class Glass[+T](var content: T) {
  def put(t: T): Unit = { content = t }
  def get: T = content
}
val glassDrink: Glass[Drink] = new Glass[Water](new Water)

反変

val glassDrink: Glass[Water] = new Glass[Drink](new Drink)

変異指定

例)Listは共変

val list: List[Any] = List[Int](1,2,3)

下限境界

sealed abstract class List[+A] extends AbstractSeq[A]
// 省略
  def ::[B >: A](x: B): List[B] = new scala.collection.immutable.::(x, this)

例)同じ要素(Int)の場合には、同じ要素(Int)のList型が作成される

scala> val list = List(2,3,4)
list: List[Int] = List(2,3,4)

scala> val listInt = 1 :: list
listInt: List[Int] = List(1,2,3,4)

例)Double型を要素に追加する場合は、Int、DoubleのスーパータイプであるAnyVal型のListが作られる

scala> val listAnyVal = 0.5 :: listInt
listAnyVal: List[AnyVal] = List(0.5,1,2,3,4)

例)String型を要素に追加する場合は、Int、StringのスーパータイプであるAny型のListが作られる

scala> val listAny = "Hello" :: listInt
listAny: List[Any] = List(Hello,1,2,3,4)

通常引数に共変型パラメータが入ると型安全が壊れる理由

例)仮に共変がOKだった場合に、Water型がJuice型に変わってしまう例

val arrayWater: Array[Water] = Array(Water,Water)

val arrayDrink: Array[Drink] = arrayWater

arrayDrink(0) = Juice

反変のメリット


Top     back     Posts     Tags     About Me