Scala概述(五)抽象(2.1、2.2)

路徑依賴類型(Path-dependent types 不知道AbsCell綁定的類型情況下,也可以對其進行訪問。下面這段代碼將一個cell的值恢復成爲其初始值(init),而無需關心cell值的類型是什麼。

def reset(c: AbsCell): unit = c.set(c.init)

爲什麼可以這樣做呢?因爲c.init的類型是c.T,而c.setc.T=>unit類型的函數,因此形參與實參類型一致,方法調用是類型正確的。

c.T是一個路徑依賴類型的例子,通常來講,這種類型的形式是:x1.x2.….xn.Tn>0),x1,…,xn是不可變的值,而Txn的類型成員。路徑依賴類型是Scala的一個新穎的特性,其理論基礎是vObj calculus[36]

路徑依賴類型要依靠其前綴路徑的不可變性,下面給出一個違反了不可變性的例子:

var flip = false

def f(): AbsCell = {

flip = !flip

if (flip) new AbsCell { type T = int; val init = 1 }

else new AbsCell { type T = String; val init = "" }

}

f().set(f().get) // illegal!

在上例中,每一次調用f()分別返回intString類型的值,因此最後一句是錯誤的,因爲它要將String類型的值賦給一個int值的cellScala類型系統禁止這種調用,因爲f().get的類型是f().T,而這不是一個有效類型,因爲f()不是一個有效路徑。

類型選擇與單例類型(Type selection and singleton typesJava中,類型定義可以嵌套,嵌套類型用其外部類型做前綴的形態表示。在Scala中,則通過“外部類型#內部類型”(Outer#Inner)的方式來表示,“#”就稱作類型選擇(Type Selection)。從概念上說,這與路徑依賴類型(例如:p.Inner)不同,因爲p是一個值,不是一個類型。進一步而言,Outer#t也是一個無效表達式,如果t是一個定義在Outer中的抽象類型的話。

實際上,路徑依賴類型可以被擴展成爲類型選擇,p.t可以看做是p.type#t,這裏p.type就稱作單例類型,僅代表p所指向對象的類型。單例類型本身對於支持方法調用串接很有作用,考慮如下代碼:C有一個incr方法,對其值+1,其子類D由一個decr方法,對其值-1

class C {

protected var x = 0

def incr: this.type = { x = x + 1; this }

}

class D extends C {

def decr: this.type = { x = x - 1; this }

}

從而我們可以將相關調用串接起來:

val d = new D; d.incr.decr

如果沒有this.type這個單例類型,上述調用是非法的,因爲d.incr的類型應該是C,但C並沒有decr方法。從這個意義上說,this.type類似於Kim Brucemytype[29]的一個協變的使用方式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章