Solution with implicit conversion
Ken suggested that a proxy could help us in this case. What we are trying to do here is to add a trait to the instance after it is created. This "monkey patching" could be useful if someone else wrote the class (and the apply()
method) and you cannot access the source. In this case you can do is add a proxy/wrapper on top of the instance by implicit conversion (no manual conversion needed):
Using the Foo
example we could do this like this:
class Foo
object Foo { def apply() = new Foo }
trait Baz { def usefulMethod(s: String) = "I am really useful, "+ s }
// ---- Proxy/Wrapper ----
class FooWithBazProxy extends Foo with Baz
// --- Implicit conversion ---
implicit def foo2FooWithBazProxy(foo: Foo): FooWithBazProxy = new FooWithBazProxy
// --- Dummy testcode ---
val foo = Foo()
println(foo.usefulMethod("not!"))
Outputs:
I am really useful, not!
The reason I do not like this example is:
Baz
doesn't use Foo
in any way. It is hard to see the reason why we would want to attach the usefulMethod()
to Foo
.
So I made a new example where the the trait we "monkey patch" into the instance actually uses the instance:
// --------- Predefined types -----------
trait Race {
def getName: String
}
class Avatar(val name: String) extends Race{
override def getName = name
}
object Avatar{
def apply() = new Avatar("Xerxes")
}
// ---------- Your new trait -----------
trait Elf extends Race {
def whoAmI = "I am "+ getName + ", the Elf. "
}
// ---- Proxy/Wrapper ----
class AvatarElfProxy(override val name: String) extends Avatar(name) with Elf
// ---- Implicit conversion ----
implicit def avatar2AvatarElfProxy(Avatar: Avatar): AvatarElfProxy = new AvatarElfProxy(Avatar.name)
// --- Dummy testcode ---
val xerxes= Avatar()
println(xerxes.whoAmI)
Prints:
I am Xerxes, the Elf.
In this example the added Elf
trait use the getName
method of the instance it extends.
Would be grateful if you see any errors, I am not the good at implicits (yet).