构造一个可重写的隐式

时间:2016-04-09 15:02:59

标签: scala implicits

我想为可以覆盖的类实现一个通用隐式。如下:

tooling.scala

package tooling    

case class Tool( msg: String)

class Toolkit{
  def usingTool(source:String)(implicit tool:Tool){
    println( s"[$source] using tool: ${tool.msg}" )
  }
}

user.scala

package user

class User{
  val toolkit = new Toolkit()

  def usingGenericTool(){
    toolkit.usingTool( "from generic usage")
  }

  def usingSpecificTool(){
    implicit lazy val tool = Tool("shovel")
    toolkit.usingTool( "from generic usage")
  }
}

如果我在伴随对象或特征中定义通用隐式Tool实现,我会收到工具和通用隐式ambiguous implicit values的警告。

如何定义一个通用隐式val,它仍然可以在方法范围内重写并在各种类中重用?

2 个答案:

答案 0 :(得分:0)

您可以添加implicit参数,就像它们是普通参数一样,即:

toolkit.usingTool("from generic usage")(Tool("shovel"))

每个隐式成员也是一个优先级 - 在祖先类中定义的隐式成员会覆盖在父类中定义的隐含,即使名称不同。

以下示例将打印2

trait LowPriorityImplicit {
  implicit val x = 1
}

object Test extends LowPriorityImplicit {
  implicit val y = 2

  def f(implicit i: Int) = println(i)

  f // => 2
}

答案 1 :(得分:0)

定义Tool的伴随对象中隐含的默认值:

case class Tool( msg: String)
object Tool {
  implicit val defaultTool: Tool = Tool("Generic")
}

您可以通过导入其他工具或创建隐式Tool变量来覆盖它:

object Tools {
  implicit val Special: Tool = Tool("special")
}

def usingTools(): Unit = {
  val toolkit = new Toolkit()
  toolkit.usingTool("using the default")

  { // importing an override
    import Tools.Special
    toolkit.usingTool("using imported")
  }

  { // creating an override
    implicit val anotherTool: Tool = Tool("local")
    toolkit.usingTool("using local implicit val")

    // using a Tool other then the currently imported as an exception:
    toolkit.usingTool("overriding once manually")(Tool("manual"))
  }
}