最新消息:XAMPP默认安装之后是很不安全的,我们只需要点击左方菜单的 "安全"选项,按照向导操作即可完成安全设置。

Scala day 24 (variances)

XAMPP下载 admin 803浏览 0评论
 variances
就是定義型別,以及型別的父子類別的繼承關係.
首先先訂幾個類別並有繼承關係 :
抽象類別 Animal、繼承 Animal 的 Cat、繼承 Cat 的 MexCat.

abstract class Animal {
def name: String
}
class Cat(catName: String) extends Animal {
def name = catName
}

class MexCat(MexCatName: String) extends Cat(MexCatName) {
override def name = MexCatName
}

Invariant
Invariant 的寫法 :

scala> class InvariantClass[A]
defined class InvariantClass
Invariant 代表說該型態就一定是要定義的那一個,像這邊定義的是 Cat 類別,所以使用時都只能用 Cat :

scala> def invarMethod(x: InvariantClass[Cat]) {}
invarMethod: (x: InvariantClass[Cat])Unit
所以這邊呼叫 invarMethod 方法時,只有 Cat 不會錯誤,MexCat 及 Animal 都會出錯 :

scala> invarMethod(new InvariantClass[MexCat])
<console>:15: error: type mismatch;
found   : InvariantClass[MexCat]
required: InvariantClass[Cat]
Note: MexCat <: Cat, but class InvariantClass is invariant in type A.
You may wish to define A as +A instead. (SLS 4.5)
invarMethod(new InvariantClass[MexCat])
^

scala>   invarMethod(new InvariantClass[Cat])

scala>   invarMethod(new InvariantClass[Animal])
<console>:15: error: type mismatch;
found   : InvariantClass[Animal]
required: InvariantClass[Cat]
Note: Animal >: Cat, but class InvariantClass is invariant in type A.
You may wish to define A as -A instead. (SLS 4.5)
invarMethod(new InvariantClass[Animal])
^

covariant
covariant 的寫法 :

scala> class CovariantClass[+A]
defined class CovariantClass
covariant 代表說,只要是 A 與有繼承 A 這個形態的類別(也就是 A 的子類別),也都可以使用 :

scala> def covarMethod(x: CovariantClass[Cat]) {}
covarMethod: (x: CovariantClass[Cat])Unit
所以呼叫 covarMethod 方法時,MexCat(Cat的子類別)以及 Cat 都會成功,只有 Animal 會失敗.

scala> covarMethod(new CovariantClass[MexCat])

scala> covarMethod(new CovariantClass[Cat])

scala> covarMethod(new CovariantClass[Animal])
<console>:15: error: type mismatch;
found   : CovariantClass[Animal]
required: CovariantClass[Cat]
covarMethod(new CovariantClass[Animal])
^

contravariant
contravariant 的寫法 :

scala> class ContravariantClass[-A]
defined class ContravariantClass
contravariant 代表說,只要是 A 與 A 這個形態的父類別,也都可以使用 :

scala> def contraMethod(x: ContravariantClass[Cat]) {}
contraMethod: (x: ContravariantClass[Cat])Unit
所以呼叫 contraMethod 方法時,Cat 以及 Animal(Cat 的父類別) 都會成功,只有 MexCat 會失敗.

scala> contraMethod(new ContravariantClass[MexCat])
<console>:15: error: type mismatch;
found   : ContravariantClass[MexCat]
required: ContravariantClass[Cat]
contraMethod(new ContravariantClass[MexCat])
^

scala> contraMethod(new ContravariantClass[Cat])

scala> contraMethod(new ContravariantClass[Animal])

接著再來用 trait 測試看看 :
定義兩個 trait OntheRoad 及 LikeFish

scala> trait OntheRoad
defined trait OntheRoad

scala> trait LikeFish
defined trait LikeFish
讓 Cat 除了繼承 Animal 並同時擁有 OntheRoad 及 LikeFish 這兩個特徵 :

scala> class Cat(catName: String) extends Animal with OntheRoad with LikeFish {
|   def name = catName
| }
defined class Cat
接著重新定義一次 function 再呼叫看看,trait 都可以成功 :

scala> def contraMethod(x: ContravariantClass[Cat]) {}
contraMethod: (x: ContravariantClass[Cat])Unit

scala> contraMethod(new ContravariantClass[OntheRoad])

scala> contraMethod(new ContravariantClass[LikeFish])

總結
在 scala 的 variances 除了可以定義型別(Invariant)又加上了可用父類別(contravariant)及子類別(covariant)的選擇,讓型態上擴充性更強.

转载请注明:XAMPP中文组官网 » Scala day 24 (variances)

您必须 登录 才能发表评论!