【发布时间】:2018-07-30 21:27:32
【问题描述】:
我已经尝试过How to override an implicit value? 中描述的解决方案,但它没有帮助。这是一个代码示例。
具有 2 种不同实现的 TestImplicit 抽象定义(类似于 ExecutionContextExecutor):
trait TestImplicit {
def f(s:String):Unit
}
object TestImplicitImpl1 extends TestImplicit {
override def f(s: String): Unit = println(s"1: $s")
}
object TestImplicitImpl2 extends TestImplicit {
override def f(s: String): Unit = println(s"2: $s")
}
在ImplDefinition 对象中,一个q 变量被定义为通过导入隐式使用(类似于ExecutionContext.Implicits.global):
object ImplDefinition {
implicit val q:TestImplicit = TestImplicitImpl1
}
定义方法的客户端,隐式接受TestImplicit(类似scala.concurrent.Future):
trait TestImplicitClient {
def fu(implicit ti:TestImplicit):Unit
}
object TestImplicitClient extends TestImplicitClient {
override def fu(implicit ti: TestImplicit): Unit = {
println("client")
ti.f("param")
}
}
下一步,客户端的客户端,选择应该使用TestImplicit 的哪个实现,通过import(类似于使用Future 的API)来决定:
object ClientOfClient {
import somepackage.ImplDefinition.q
def t():Unit =
TestImplicitClient.fu
}
现在在测试中,我想使用这个ClientOfClient.t(),但我需要覆盖隐式,并改用TestImplicitImpl2。背后的主要思想 - 隐式应该由 API 的客户端定义/覆盖,而不是 API 本身:
import somepackage.{ClientOfClient, TestImplicit, TestImplicitImpl2}
import org.junit.Test
class ImplTest {
// trying to hide it via import, does not help
import somepackage.ImplDefinition.{q => _,_}
@Test def test(): Unit ={
//trying to hide it via downgrading to non-implicit, does not work either
val q = somepackage.ImplDefinition.q
implicit val ti = TestImplicitImpl2
ClientOfClient.t()
}
}
每次我运行测试时,我都会得到输出:
client
1: param
但没想到:
client
2: param
我该如何解决?我需要一种方法来允许客户端覆盖隐式并尽可能使用简单的 API。这意味着,我不想在 ClientOfClient.t() 方法中添加额外的隐式参数。
【问题讨论】:
标签: scala implicit overriding