Given a trait MyTrait
:
trait MyTrait {
def doSomething = println("boo")
}
it can be mixed into a class with extends
or with
:
class MyClass extends MyTrait
It can also be mixed upon instantiating a new instance:
var o = new MyOtherClass with MyTrait
o.doSomething
But...can the trait (or any other if that makes a difference) be added to an existing instance?
I'm loading objects using JPA in Java and I'd like to add some functionality to them using traits. Is it possible at all?
I'd like to be able to mix in a trait as follows:
var o = DBHelper.loadMyEntityFromDB(primaryKey);
o = o with MyTrait //adding trait here, rather than during construction
o.doSomething
Why not use Scala's extend my library pattern?
https://alvinalexander.com/scala/scala-2.10-implicit-class-example
I'm not sure what the return value is of:
var o = DBHelper.loadMyEntityFromDB(primaryKey);
but let us say, it is
DBEntity
for our example. You can take the class DBEntity and convert it to a class that extends your trait,MyTrait
.Something like:
I believe you could also simplify this by just using an implicit class.
I particularly dislike the accepted answer here, b/c it overloads the
::
operator to mix-in a trait.In Scala, the
::
operator is used for sequences, i.e.:Using it as a means of inheritance feels, IMHO, a little awkward.
An existing runtime object in the JVM has a certain size on the heap. Adding a trait to it would mean altering its size on the heap, and changing its signature.
So the only way to go would be to do some kind of transformation at compile time.
Mixin composition in Scala occurs at compile time. What compiler could potentially do is create a wrapper B around an existing object A with the same type that simply forwards all calls to the existing object A, and then mix in a trait T to B. This, however, is not implemented. It is questionable when this would be possible, since the object A could be an instance of a final class, which cannot be extended.
In summary, mixin composition is not possible on existing object instances.
UPDATED:
Related to the smart solution proposed by Googol Shan, and generalizing it to work with any trait, this is as far as I got. The idea is to extract the common mixin functionality in the
DynamicMixinCompanion
trait. The client should then create a companion object extendingDynamicMixinCompanion
for each trait he wants to have the dynamic mixin functionality for. This companion object requires defining the anonymous trait object gets created (::
).I usually used a
implicit
to mix in a new method to an existing object.See, if I have some code as below:
and then you can use
MyTrait
method with an already existing object Test.in your example, you can use like this:
I am thinking out a prefect syntax to define this HelperObject:
What about an implicit class? It seems easier to me compared to the way in the other answers with a final inner class and a "mixin"-function.
I have a idea for this usage:
you can use this trait as below:
for your example code:
I hope this can help you.
UPDATED
but this pattern has some restrict, you can't use some implicit helper method that defined already.