我有一个接受类型参数的类,我希望类上的方法被限制为遵循该参数化的参数。但是,当具体实例化类时,类型参数具有混合的其他特征,我想忽略该方法。具体地:
trait X {def str = "X"}
trait X1 extends X {def str = "X1"}
trait X2 extends X {def str = "X1"}
trait Y
class Foo[A <: X] { def do(a:A) = a.str}
val f = new Foo[X1 with Y]
val x1 = new X1 {}
val x2 = new X2 {}
val y = new Y {}
// I want this to compile
f.do(x1)
// and these to not compile
f.do(x2)
f.do(y)
目前三个最终语句都没有编译,但是我想在Foo.do
方法上设置type参数,以便只编译第一个语句。我不知道如何从声明中“提取”A
类型的适当部分。
答案 0 :(得分:1)
我已经找到了一个解决方案,虽然它不是太优雅,而且我对其他人开放。因为,通过假设,我只会在我的X
方法中使用do
上的方法(因为它们是唯一可见的类型)我可以使用一个输入参数转换为适当的类型隐含如下:
trait X {def str = "X"}
trait X1 extends X {override def str = "X1"}
trait X2 extends X {override def str = "X1"}
trait Y
trait X {def str = "X"}
implicit def x2xWy[Xt <: X](x:Xt):Xt with Y = x.asInstanceOf[Xt with Y]
class Foo[A <: X] { def doIt[A1](a:A1)(implicit toA:(A1 => A)) = toA(a).str}
// this compiles
f.doIt(x1)
// and these do not
f.doIt(x2)
f.doIt(y)
也就是说,这种方法在几个方面仍然不是最理想的,即我们需要在编译时知道在运行时可能混入A
的所有类型。此外,需要仔细管理隐含的范围,以确保它不会泄漏到可能导致问题的情况。