我有以下问题,这可能是最好的例子:
1) 此代码在库中提供
sealed trait Base
class A extends Base
class B extends Base
class C extends Base
trait IntValue[T <: Base] {
def value: Int
}
trait SomeApi {
def apply[T <: Base : ClassTag]: Int
}
class ApiUsage(val api: SomeApi) {
def someMethod() = {
println(api[A])
println(api[B])
println(api[C])
}
}
SomeApi#apply方法应根据Base特性的运行时类型返回Int值。我知道这个例子没有道理,但我尽量让它变得简单。在实际库中,此方法从actor系统返回对基于该类型的akka actor的引用。
2) 现在,我想使用ApiUsage类,并通过隐式为Base特征的类型提供值,类似于
object Test extends App {
implicit val aValue = new IntValue[A] {
def value: Int = 10
}
implicit val bValue = new IntValue[B] {
def value: Int = 20
}
implicit def defaultValue[T <: Base : ClassTag] = new IntValue[T] {
def value: Int = 30
}
private val api = new SomeApi {
def apply[T <: Base : ClassTag]: Int = findValue[T]
}
private def findValue[T <: Base : IntValue : ClassTag] =
implicitly[IntValue[T]].value
val apiUsage = new ApiUsage(api)
apiUsage.someMethod()
}
我想在那里创建ApiUsage类,并将其引用传递给我的SomeApi本地实现,该实现返回:-10适用于A类型-20用于B类型-30用于其他类型(C在这种情况下)
此测试在所有情况下都打印30。
有没有什么方法可以用隐词优雅地解决这个问题?非常感谢
在不更改签名的情况下,最好的方法可能是
val api = new SomeApi {
def apply[T <: Base : ClassTag]: Int = {
val clazz = classTag[T].runtimeClass
if (clazz == classOf[A])
10
else if (clazz == classOf[B])
20
else
30
}
}