![](/img/trans.png)
[英]Why can't I call a method with parameter `this` in a class extending a generic trait?
[英]Scala can't find case class parameter in generic trait method
我有以下案例 class 使用通用方法實現特征。 目標是讓每個擴展特征的 class S
以該方法使用S
S
的值的方式實現該方法。
case class Foo(x: Int) extends Bar {
def baz[Foo](v: Foo): Foo = {
Foo(v.x + x)
}
}
trait Bar {
def baz[S <: Bar](v: S): S
}
但是,在編譯時,我收到以下錯誤,即找不到x
。
error: value x is not a member of type parameter Foo
Foo(v.x + x)
^
one error found
對我來說更奇怪的是,當我將方法更改為返回Foo(3)
(從而刪除對x
的訪問)時,我收到以下錯誤:
error: type mismatch;
found : <empty>.Foo
required: Foo(in method baz)
Foo(3)
^
one error found
我不確定<empty>.Foo
和Foo(in method baz)
類型是什么,以及為什么這兩個不僅僅是Foo
。 顯然,我對 Scala 的類型系統有一些誤解,因此不勝感激。
編輯
我希望有多個類實現Bar
。 我希望能夠在Bar
類型的 val 上調用baz
。
在下面的示例中考慮a
和b
是從其他地方獲得的,根據我的程序的邏輯,我知道它們都是相同 class 的實例(不一定是Foo
)。 在這種情況下,有什么辦法可以合法地打電話給baz
嗎? 我知道我可以將兩者都轉換為Foo
,但這發生在我不知道具體的 class 是什么的情況下。 也就是說,我知道a
和b
的類型都是T <: Bar
相同的T
,但我不知道T
是什么。
object Foo {
def main(args: Array[String]): Unit = {
val a: Bar[_] = Foo(3)
val b: Bar[_] = Foo(2)
a.baz(b) // This call is invalid
}
}
baz
的類型參數不像你想象的那樣工作。 在原始特征Bar
中,它告訴您可以傳入任何擴展Bar
和baz
的S
將 output 另一個S
。 這意味着在Foo
中,您不僅要處理Foo
還要處理從Bar
繼承的其他類。
此外,類型參數Foo
會影響 class Foo
。 它等價於:
case class Foo(x: Int) extends Bar {
def baz[T](v: T): T = {
Foo(v.x + 1)
}
}
T
與Foo
和Bar
完全無關,因此您的方法也不滿足baz
的簽名,因為它實際上應該是T <: Bar
。
我認為你想要做的是通過給Bar
本身的類型參數S
(這稱為 F 有界多態性):
case class Foo(x: Int) extends Bar[Foo] {
def baz(v: Foo): Foo = {
Foo(v.x + 1)
}
}
trait Bar[S <: Bar[S]] { this: S =>
def baz(v: S): S
}
這里的S
基本上可以用來指代 class 擴展Bar
的類型,因此編譯器知道baz
輸入和輸出Foo
s。
您以后可以像這樣使用它:
def test[T <: Bar[T]](a: T, b: T) = a.baz(b)
但是,根據您的編輯,您似乎想要一個類型類。 我建議將Bar
的定義更改為以下內容:
trait Bar[T] {
def baz(t: T): T
}
然后Foo
可以這樣定義:
case class Foo(x: Int)
Foo
的Bar
的隱式實例將單獨提供(可能在Bar
的伴隨對象中):
object Bar {
implicit val fooBar: Bar[Foo] = new Bar {
def baz(v: Foo): Foo = Foo(v.x + 1)
}
//For convenience
def apply[T](implicit bar: Bar[T]): bar
}
您以后可以像這樣使用它:
def test[T : Bar](a: T, b: T) = Baz[T].bar(a, b)
有關返回電流類型問題的更多信息,請參閱 F-bounded polymorphism over typeclass 的優勢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.