你剛剛告訴類型傳遞給你的類爲T
和S
應該是平等的編譯器 - 你只需要他們的平等,它可以被用來推斷實際的證據T
和S
正確,當你經過實際類型(但不在泛型類本身內)。這並不意味着T
和S
是可互換的。順便說一句,它不會改變任何東西,但你通過定義新S
和T
做了一個錯誤,應該是:
class Pair[T, S](var first: T, var second: S) {
def swap(implicit ev: T =:= S) { //without [S, T] - they are unrelated to original ones, it's whole new names
val temp = first
first = second // doesn't compile
second = temp
}
}
但是它仍然不能編譯。爲什麼?試想一下:
def getBoth(implicit ev: T =:= S) = List(first, second)
那麼什麼是返回類型編譯器應該推斷? List[T]
或List[S]
。唯一可以做的是List[Any]
。所以相同和不同類型的模擬沒有任何意義。如果你想要不同的名字 - 只需使用type S = T
就不需要證據。
什麼是S
和T
不同的構造方法和在某些方法相同的真實情況。這在邏輯上是不正確的(當談論抽象類型時 - 不是具體的替換)。
Btw,=:=
不是編譯器功能 - 在編譯器中沒有特殊處理。整個實施是它裏面斯卡拉Predef
:
@implicitNotFound(msg = "Cannot prove that ${From} =:= ${To}.")
sealed abstract class =:=[From, To] extends (From => To) with Serializable
private[this] final val singleton_=:= = new =:=[Any,Any] { def apply(x: Any): Any = x }
object =:= {
implicit def tpEquals[A]: A =:= A = singleton_=:=.asInstanceOf[A =:= A]
}
所以它只是tpEquals[A]
隱含這需要鍵入A
,讓您A =:= A
- 當你需要T =:= U
它試圖做這樣的轉換,只有同等類型是可能的。只有當你通過實際的T
和U
,而不是當你定義它們時,檢查隱式本身的過程實際上只發生。
關於你的具體問題:
class Pair[T, S](var first: T, var second: S) {
def swap(implicit ev: T =:= S) {
val temp = first
first = second.asInstanceOf[T]
second = temp.asInstanceOf[S]
}
}
scala> new Pair(5,6)
res9: Pair[Int,Int] = [email protected]
scala> res9.swap
scala> res9.first
res11: Int = 6
或者只是(如@mz和@Imm建議):
class Pair[T, S](var first: T, var second: S) {
def swap(implicit ev: T =:= S, ev2: S =:= T) {
val temp = first
first = second
second = temp
}
}
T =:= S
擴展T => S
這隱含地添加功能(甚至作爲一個對象)解釋爲在Scala中從T
到S
的隱式轉換,所以它適用於兩種類型是相同的,這非常酷。
你怎麼解決給定的問題呢?從問題陳述「給定可變對[S,T]類...」,我猜測作者不希望我在類級別上定義隱式證據,但僅在方法級別上定義。 –
你已經解決了這個問題 - 只要做'asInstanceOf [S]','asInstanceOf [T]'。我只是說,編譯器不能爲你自動完成,一般情況下 – dk14
謝謝你,我已經接受你的答案,也贊成它。 –