2016-04-09 1 views
3

Je voudrais implémenter un implicite générique pour une classe qui peut être surchargée. Comme ce qui suit:Construire un implicite substituable

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

Si je définis un Tool implicite générique dans la mise en œuvre d'un objet compagnon ou d'un trait, je reçois l'avertissement cet outil et le générique implicite sont ambiguous implicit values.

Comment puis-je définir un valise implicite générique qui peut encore être substitué dans la portée d'une méthode et réutilisé dans diverses classes?

Répondre

0

Vous pouvez simplement ajouter implicit paramètres comme si elles étaient les ordinaires, à savoir:

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

De plus, chaque membre implicite est une priorité - implicite qui sont définies dans les classes d'ancêtre remplace implicits définies dans les classes parent, même avec nom différent.

Ainsi, l'exemple suivant imprimera 2:

trait LowPriorityImplicit { 
    implicit val x = 1 
} 

object Test extends LowPriorityImplicit { 
    implicit val y = 2 

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

    f // => 2 
} 
+0

Je ne veux pas, puisque je vais appeler cette méthode plusieurs fois – dstibbe

+0

Pour autant que je sache, il n'y a pas de mécanisme de priorité pour les implicits définis dans la même classe. Pour implicits dans la hiérarchie de classe - j'ai mis à jour ma réponse. – Maxim

+0

Mais si je définis l'implicite dans le trait Test, comme vous l'avez montré dans votre exemple, JE NE PEUX PAS définir un implicite dans le corps de la méthode de la classe Test. – dstibbe

0

Définir la valeur par défaut implicite dans l'objet compagnon de Tool:

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

Et vous pouvez la remplacer par l'importation d'autres outils, ou la création d'un implicite Tool variable:

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