我想在特征中访问该特征的类型参数的类型参数。不添加这个“二阶”类型参数作为特征的另一个“一阶”参数。以下说明了这个问题:
sealed trait A; sealed trait A1 extends A; sealed trait A2 extends A
trait B[ ASpecific <: A ] { type ASpec = ASpecific }
trait D[ ASpecific <: A ] extends B[ ASpecific ]
trait C[ +BSpecific <: B[ _ <: A ]] {
def unaryOp : C[ D[ BSpecific#ASpec ]]
}
def test( c: C[ B[ A1 ]]) : C[ D[ A1 ]] = c.unaryOp
测试无法编译,因为显然,c.unaryOp的结果是类型C [D [A]]而不是C [D [A1]],表明ASpec只是_&lt;:A的快捷方式并且没有引用具体的类型参数。
双类型参数解决方案很简单:
sealed trait A; sealed trait A1 extends A; sealed trait A2 extends A
trait B[ ASpecific <: A ]
trait D[ ASpecific <: A ] extends B[ ASpecific ]
trait C[ ASpecific <: A, +BSpecific <: B[ ASpecific ]] {
def unaryOp : C[ ASpecific, D[ ASpecific ]]
}
def test( c: C[ A1, B[ A1 ]]) : C[ A1, D[ A1 ]] = c.unaryOp
但我不明白为什么我需要用第二个显然多余的参数来混淆我的源代码。有没有办法从特质B中检索它?
答案 0 :(得分:1)
我可以通过在C
中添加类型别名来进行编译:
sealed trait A; sealed trait A1 extends A; sealed trait A2 extends A
trait B[ ASpecific <: A ] { type ASpec = ASpecific }
trait D[ ASpecific <: A ] extends B[ ASpecific ]
trait C[ +BSpecific <: B[ _ <: A ]] {
type BSpec = BSpecific#ASpec
def unaryOp : C[ D[ BSpec ]]
}
def test[X <: C[ B[ A1 ]]](c:X): C[ D[ X#BSpec ]] = c.unaryOp
另一个增强版测试:
def test2[K <: A, X <: C[ B[ K ]]](c:X): C[ D[ X#BSpec ]] = c.unaryOp
希望它没有改变你的意图。
答案 1 :(得分:0)
@pedrofurla(抱歉无法直接回复,因为我没有登录就问到了)
虽然您的示例已编译,但我认为除了C[D[A]]
之外您没有得到任何内容,因为X#BSpec
正是_ <: A
的别名......
val x: C[D[A1]] = test(new C[B[A1]] {})
<console>:34: error: type mismatch;
found : C[D[A]]
required: C[D[A1]]
val x: C[D[A1]] = test(new C[B[A1]] {})
^