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.
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.