Search code examples
scalaimplicit-conversion

How to access an implicit conversion defined a class (in Scala)?


I have an abstract class like so:

abstract class Base {
  val myInners = mutable.ArrayBuffer[Inner[Any]]()
  abstract class Inner[+T] {
    myInners += this
    def get: T
    // other functionality here
  }
  implicit def innerToValue[T](inner: Inner[T]) = inner.get
  class IntInner extends Inner[Int] { ... }
  class StringInner extends Inner[String] { ... }
  ...
}

Initially I had a singleton object like

object MyObject extends Base {
  val intVal = new IntInner()
  val stringVal = new StringInner()
  ...
}

And I was able to use these object members elsewhere like functionThatExpectsAnInteger(MyObject.intVal) which made me happy :).

In order to improve testability, though, I'd like to make this object into a class and inject an instance of that class wherever it's being used. However by making MyObject into a class, I seem to be unable to use this implicit conversion anymore regardless of what I've tried, which makes me sad :(.

Of course, this conversion only saves me calling a get method, and I can live without it, but I'm still learning about scala implicits and I'd like to understand why this doesn't work and if there is a way to do this.


Solution

  • Something feels a bit odd about your implicits but I assume this is just an example so I'm not going to go into the details.

    The reason I see for why this doesn't work would be that implicits are looked up by the compiler if in scope of the companion object. If you turn it into a class you'll have to import it first. One way of doing that would be the following:

    val obj = new MyObject()
    import obj.innerToValue
    val x : Int = obj.intVal
    

    I'm sure this could be done nicer but only by changing the structure of the code overall.