Search code examples
scalatraitscomposition

How to get implicit and explicit identical value to align when both being mixed in


Assume the following situation

  • I have a trait A and a trait B that both declare a value that has the same name and type.

  • A defines the value explicitly, while B defines it implicitly

  • A and B are from external libraries and can not be changed. I don't want to fork.

  • I want to use both of them in a class C that is in my own code

How can I get them to align inside class C? I want B.foo to be the value from A.foo

// External code, cant touch
trait A{
  val foo = "boom"
}
trait B{ 
  implicit val foo: String
}

// My class
class C extends A with B {
  //uh oh??
}

Update (with help from Jasper-M)

// External code, cant touch
trait A{
  val foo = "boom"
}
trait B{
  implicit val foo: String

  def implBang()(implicit s: String) = s

  def doTheBang() = implBang()
}

// My class
class C extends B with A {}

new C().doTheBang; // Prints "boom"

Now only question remaining, how would I get foo to be in the implicit scope for class C?


Solution

  • Ideally you can select the implementation you want with super[Name]. But for vals that doesn't work for some reason.

    class C extends A with B {
      override implicit val foo = super[A].foo
      // error: super may not be used on value foo
    }
    

    So if you really need some implicit String in C I would suggest just letting linearization do its thing and define another implicit val.

    class C extends A with B {
      implicit val bar = foo
    }