code

2016年10月27日 星期四

Scala筆記 14 - type bounds & covariant

Type Bounds

OOP裡面有subclassing的關係,一個superclass pointer可以指向其subclass instance,因為所有能在supertype執行的動作與屬性,都能在其subclass做到。

subclassing是polymorphism的一種。

Scala提供另一種polymorphism: generics。

假設有一個function定義如下:


IntSet假設有兩個subclass: NonEmpty 以及 Empty。

所以這個assertAllPos有可能接受任一種subclass instance,也有可能回傳任一種subclass instance。

不過其實際上執行的邏輯是:如果input是NonEmpty,則output一定是NonEmpty,對Empty來說也是一樣。

所以Scala可以利用generics和“type bounds”來達成這種更正確的宣告。
“A <: B”意思是A是B的subclass



用簡單例子來看,假設有以下class hierarchy:

class A {}
class B extends A {}
class C extends A {}
class D extends B {}

def f(x: A): A = { x }
def f2[T <: A](x: T): T = x //我們接受和回傳的type T只能是A的subtype(包括A)


如果執行以下statement,則可以看出return type都是A:

f(new A)
f(new B)
f(new C)
f(new D)

res0: A = A@63f64c3c
res1: A = B@48034736
res2: A = C@4d2b401b
res3: A = D@7fdb9e4e

但是如果執行f2,可以看出input type就是return type,因為我們使用了 type parameter [T <: A]

f2(new A)
f2(new B)
f2(new C)
f2(new D)

res4: A = A@192224
res5: B = B@152f208
res6: C = C@148d260e
res7: D = D@4c13ac62

我們也可以同時設定upper and lower type bound,這樣限定可以input的type:

def f3[T >:D <: B](x: T) : T = x

//f3(new A) //不符合type boundsf3(new B)
//f3(new C) //不符合type bounds
f3(new D)


Type Covaraint

所謂type convariant是指,如果B是A的subclass,那 List[B]也是List[A]的subclass呢? Scala的compiler並不是type covariant,所以在compile time就會抓出error,而早期的Java compiler因為沒有generics,所以為了達成某些reusability,在compile time是type covariant,但是依賴runtime check。


沒有留言:

張貼留言