How to provide default value for implicit parameters at class level

后端 未结 2 1086
野趣味
野趣味 2021-02-01 17:57

I\'m trying to define a class with some methods taking an implicit parameter :

object Greetings {
  def say(name: String)(implicit greetings: String): String = g         


        
相关标签:
2条回答
  • 2021-02-01 18:31

    I've found a workaround:

    class Greetings(implicit val greetings: String = "hello") {
        def say(name: String): String = greetings + " " + name 
    }
    

    Like this I can have a default value and override it if I want:

    new Greetings().say("loic")                     //> res0: String = hello loic
    
    implicit val greetings = "hi"                   //> greetings  : java.lang.String = hi
    new Greetings().say("loic")                     //> res1: String = hi loic
    
    new Greetings()("coucou").say("loic")           //> res2: String = coucou loic
    

    Note: new Greetings()("coucou") is working, not new Greetings("coucou") , because of a syntax strangeness explained here.

    0 讨论(0)
  • 2021-02-01 18:34

    It is a bad idea to use such a general type as String in an implicit. The main reason is that implicit lookup is solely base on the type, so what if someone else defines another implicit value of type String? You might end up with a conflict. So you should define your own specific type for your own purpose (a simple wrapper around String).

    Another reason is that when looking for implicit values, the compiler will look (among other places) into the companion object (if any) of the implicit value type. You can easily see how useful it is, as the companion object is the natural place to put a default implicit value (as in your case). But if the implicit value is of a type that you don't own (such as String) you just cannot write a companion object for it, while with your own wrapper type there is no problem.

    OK, enough verbiage, here is how you can do it:

    case class Greetings( value: String ) {
      override def toString = value
    }
    object Greetings {
      // this implicit is just so that we don't have to manually wrap 
      // the string when explicitly passing a Greetings instance
      implicit def stringToGreetings( value: String ) = Greetings( value ) 
    
      // default implicit Greetings value
      implicit val greetings: Greetings ="hello"
    
      def say(name: String)(implicit greetings: Greetings): String = greetings + " " +name 
    }
    Greetings.say("loic")                         
    Greetings.say("loic")("hi") 
    
    0 讨论(0)
提交回复
热议问题