[英]Implicits via method/constructor arguments vs using implicitly
此代碼編譯並完成預期的操作
class MyList[T](list: T)(implicit o: Ordering[T])
但是,這不是:
class MyList2[T](list: T) {
val o = implicitly[Ordering[T]]
}
我不明白為什么。 在構造類的第一個示例中,編譯器將發現Ordering隱式,因為它將知道具體類型T
但在第二種情況下,它也應該找到隱含的,因為T
已經是一個具體的類型。
在構造類的第一個示例中,編譯器將發現Ordering隱式,因為它將知道具體類型T.
在第一個示例中,需要在范圍內具有隱式Ordering[T]
,以便編譯器找到它。 編譯器本身不會“彌補”暗示。 由於您直接要求通過第二個參數列表提供一個,如果存在這樣的隱式,它將被傳遞給類構造函數。
但在第二種情況下,它也應該找到隱含的,因為
T
已經是一個具體的類型。
在編譯時T
是具體類型這一事實無助於編譯器找到它的隱含。 當我們說T
是具體類型時,你必須記住,在調用站點, T
只是一個泛型類型參數,僅此而已。 如果您不幫助編譯器,則無法保證具有隱式范圍。 您需要讓方法提供一個隱式,這可以通過Context Bound完成 :
class MyList2[T: Ordering](list: T)
這需要在編譯時存在類型T
的排序。 從語義上講,這相當於您的第二個參數列表。
您必須始終告訴編譯器應為您的類型提供隱式。 也就是說,你必須總是implicit o: Ordering[T]
。 implicitly
是,它允許您在未命名的情況下訪問隱式。 請注意,您可以對隱式參數使用語法糖(稱為“上下文綁定”),在這種情況下implicitly
變為必需:
class MyList2[T : Ordering](list: T) {
val o = implicitly[Ordering[T]]
}
類型[T : Ordering]
是“范圍內存在隱式Ordering[T]
某些類型T
”的簡寫。 它和寫作一樣:
class MyList2[T](list: T)(implicit o: Ordering[T]) {
}
但在這種情況下implicitly
不需要,因為您可以通過其標識符o
訪問隱式參數。
但在第二種情況下,它也應該找到隱含的,因為T已經是一個具體的類型。
Scala(和Java)泛型不像C ++模板那樣工作。 編譯器不會在其他地方看到MyList2[Int]
,生成
class MyList2_Int(list: Int) {
val o = implicitly[Ordering[Int]]
}
和typecheck 那個定義。 它是MyList2
本身,它沒有具體的T
。
要使第二個工作,您需要使用上下文綁定指定類型T
的Ordering
:
class MyList2[T : Ordering](list: T) {
val o = implicitly[Ordering[T]]
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.