[英]Features of different kinds of path-dependent types in scala
假設有一個特征:
trait OuterTrait {
type InnerType
}
現在我們可以寫一些非泛型函數someAlgo
:
def pairToString[S, U](x: S, y: U): String =
"{" + y.toString + " in " + x.toString + "}"
def pairPrintln[S, U](x: S, y: U) {
println(pairToString(x, y))
}
def someAlgo(x: OuterTrait)(y: x.InnerType): x.InnerType = {
pairPrintln(x, y)
y
}
和一系列通用功能:
def someAlgoObjObj[T <: OuterTrait](x: T)(y: x.InnerType): x.InnerType = {
pairPrintln(x, y)
y
}
def someAlgoObjType[T <: OuterTrait](x: T)(y: x.InnerType): T#InnerType = {
pairPrintln(x, y)
y
}
def someAlgoTypeType[T <: OuterTrait](x: T)(y: T#InnerType): T#InnerType = {
pairPrintln(x, y)
y
}
而另一個通用函數不編譯:
def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = {
pairPrintln(x, y)
y
}
看來:1) someAlgo
和someAlgoObjObj
是最正確的功能; 2)在這個例子中根本沒有使用泛型函數的意義。
我想澄清上面的通用函數之間的一些差異。 請糾正我,如果我犯了錯誤。
因此,據我所知,類型T
對應於靜態類型的x
(稱為X
)或顯式類型的通用調用(我的意思是algo[Int]
)。 這就是T#InnerType
對應於X
類型聲明中的類型的原因。 但x.InnerType
也相當於InnerType
靜態類型的x
。 區別在哪里?
進一步... someAlgoObjType
編譯,因此似乎x.InnerType
必須是T#InnerType
子類型 。 然后, someAlgoTypeObj
無法編譯,因為我們無法隱式地進行向下轉換。 雖然我們可以改寫最后一個:
def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = {
pairPrintln(x, y)
y.asInstanceOf[x.InnerType]
}
UPD1:我發現someAlgoObjObj
和someAlgoTypeType
之間存在一個區別,如果將它們與顯式類型參數一起使用。 如果我們編寫一些擴展OuterTrait
類:
class OuterIntClass extends OuterTrait{
type InnerType = Int
}
val x: OuterIntClass = new OuterIntClass()
val y: Int = 5
然后:
someAlgoObjObj[OuterTrait](x)(y) // OK
和下一個電話不起作用:
someAlgoTypeType[OuterTrait](x)(y)
T#InnerType
表示“屬於某些 T的內部類型”,而x.InnerType
表示“屬於給定 x(類型為OuterTrait)的內部類型”。
理解這些的關鍵在於給定x 中的一些T vs。 你可以將某些解釋為某些T但我們沒有哪個T實例 ,這意味着在兩個Ts中不一定相同,因此,T#InnerType不能被證明等於另一個T#InnerType。
我們來分析一下簽名:
/* 1 */ def someAlgoObjObj[T <: OuterTrait](x: T)(y: x.InnerType): x.InnerType = ???
/* 2 */ def someAlgoObjType[T <: OuterTrait](x: T)(y: x.InnerType): T#InnerType = ???
/* 3 */ def someAlgoTypeType[T <: OuterTrait](x: T)(y: T#InnerType): T#InnerType = ???
現在為第四個:
def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = y
簽名讀取:給定屬於某些T的 x和InnerType,返回屬於此x的InnerType。 但是在實現中,我們嘗試返回y,它屬於一個不一定與x相同的T,因此編譯器會抱怨。
關於更新的小注釋。
someAlgoTypeType[OuterTrait](x)(y)
Failes,因為你的方法簽名告訴它期望它的y
參數符合T#InnerType
類型,你的y.type
是Int。 要使其工作,您應該將其類型更改為以下內容:
class OuterIntClass extends OuterTrait{
type InnerType = Int
}
val x: OuterIntClass = new OuterIntClass()
val y: x.InnerType = 5
現在y
的類型滿足類型投影T#InnerType
和someAlgoTypeType[OuterTrait](x)(y)
編譯
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.