2016-04-09 9 views
3

Ich möchte ein generisches implizit für eine Klasse implementieren, die überschrieben werden kann. Wie folgt:Konstruieren eines Overridable implizit

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") 
    } 
} 

Wenn ich eine generische implizite Tool Implementierung in einem Begleitobjekt oder Merkmal definieren, erhalte ich die Warnung dass Werkzeug und die generische implizit sind ambiguous implicit values.

Wie kann ich ein generisches implizites val definieren, das im Rahmen einer Methode noch überschrieben und in verschiedenen Klassen wiederverwendet werden kann?

Antwort

0

können Sie fügen Sie einfach implicit Parameter, als ob sie gewöhnliche waren, das heißt:

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

auch jede implizite Mitglied ist eine Priorität - implizit, die in Vorgängerklassen definiert sind, überschreibt implicits in Klassen Eltern definiert, auch mit anderer Name.

So das folgende Beispiel 2 drucken:

trait LowPriorityImplicit { 
    implicit val x = 1 
} 

object Test extends LowPriorityImplicit { 
    implicit val y = 2 

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

    f // => 2 
} 
+0

Ich will nicht, da ich diese Methode mehrmals aufrufen werde – dstibbe

+0

Soweit ich weiß, gibt es keinen Prioritätsmechanismus für implicits, die in derselben Klasse definiert sind. Für die Klassenhierarchie - ich habe meine Antwort aktualisiert. – Maxim

+0

Aber wenn ich das implizit im Test-Merkmal definiere, wie Sie in Ihrem Beispiel gezeigt haben, kann ich kein implizites Element im Methodenkörper der Test-Klasse definieren. – dstibbe

0

Legen Sie den Standard implizit in dem Begleitobjekt der Tool:

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

Und Sie können es überschreiben, indem andere Werkzeuge zu importieren, oder eine Schaffung implizit Tool variabel:

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")) 
    } 
}