How to mix a line with an example?

Given the MyTrait :

 trait MyTrait { def doSomething = println("boo") } 

it can be mixed in a class with extends or with :

 class MyClass extends MyTrait 

It can also be mixed when creating an instance of a new instance:

 var o = new MyOtherClass with MyTrait o.doSomething 

But ... can an attribute (or any other, if that matters) add to an existing instance?

I load objects using JPA in Java, and I would like to add some functions to them using traits. Is it possible at all?

I would like to be able to mix in a tag as follows:

 var o = DBHelper.loadMyEntityFromDB(primaryKey); o = o with MyTrait //adding trait here, rather than during construction o.doSomething 
+43
scala traits
Oct 08 2018-10-10
source share
4 answers

I have an idea for this use:

 //if I had a class like this final class Test { def f = println("foo") } trait MyTrait { def doSomething = { println("boo") } } object MyTrait { implicit def innerObj(o:MixTest) = o.obj def ::(o:Test) = new MixTest(o) final class MixTest private[MyTrait](val obj:Test) extends MyTrait } 

You can use this feature as shown below:

 import MyTrait._ val a = new Test val b = a :: MyTrait b.doSomething bf 

for your example code:

 val o = DBHelper.loadMyEntityFromDB(primaryKey) :: MyTrait o.doSomething 

Hope this helps you.

UPDATED

 object AnyTrait { implicit def innerObj[T](o: MixTest[T]):T = o.obj def ::[T](o: T) = new MixTest(o) final class MixTest[T] private[AnyTrait](val obj: T) extends MyTrait } 

but this template has some limitation, you cannot use some implicit helper method that is already defined.

 val a = new Test af val b = a :: AnyTrait b.f1 bf val c = "say hello to %s" :: AnyTrait println(c.intern) // you can invoke String method println(c.format("MyTrait")) //WRONG. you can't invoke StringLike method, though there defined a implicit method in Predef can transform String to StringLike, but implicit restrict one level transform, you can't transform MixTest to String then to StringLike. c.f1 val d = 1 :: AnyTrait println(d.toLong) d.toHexString // WRONG, the same as above d.f1 
+24
09 Oct 2018-10-10
source share

An existing run-time object in the JVM has a specific size on the heap. Adding a tag to it would mean changing its size on the heap and changing its signature.

So the only way to go is to do some kind of conversion at compile time.

The composition of the mixture in Scala occurs at compile time. The compiler could potentially create a wrapper B around an existing object A with the same type, which simply redirects all calls to the existing object A, and then mixes with the tag T from B. This, however, is not implemented. This may be a question when it would be possible, since object A may be an instance of a finite class that cannot be extended.

Therefore, mixin composition is not possible in existing object instances.

UPDATED:

In connection with the smart solution proposed by Gogol-Shan, and summarizing it to work with any sign, this is, as I understand it. The idea is to extract the general mixin functionality into the DynamicMixinCompanion . Then, the client must create a companion object that extends the DynamicMixinCompanion for each attribute for which he wants to have dynamic mixin functionality. This companion object requires the definition of creating an anonymous object object ( :: .

 trait DynamicMixinCompanion[TT] { implicit def baseObject[OT](o: Mixin[OT]): OT = o.obj def ::[OT](o: OT): Mixin[OT] with TT class Mixin[OT] protected[DynamicMixinCompanion](val obj: OT) } trait OtherTrait { def traitOperation = println("any trait") } object OtherTrait extends DynamicMixinCompanion[OtherTrait] { def ::[T](o: T) = new Mixin(o) with OtherTrait } object Main { def main(args: Array[String]) { val a = "some string" val m = a :: OtherTrait m.traitOperation println(m.length) } } 
+20
Oct 08 2018-10-10
source share

I usually used implicit to mix a new method with an existing object.

See if I have code as below:

 final class Test { def f = "Just a Test" ...some other method } trait MyTrait { def doSomething = { println("boo") } } object HelperObject { implicit def innerObj(o:MixTest) = o.obj def mixWith(o:Test) = new MixTest(o) final class MixTest private[HelperObject](obj:Test) extends MyTrait } 

and then you can use the MyTrait method with an existing object test.

 val a = new Test import HelperObject._ val b = HelperObject.mixWith(a) println(bf) b.doSomething 

in your example, you can use like this:

 import HelperObject._ val o = mixWith(DBHelper.loadMyEntityFromDB(primaryKey)); o.doSomething 

I review prefect syntax to define this HelperObject:

 trait MyTrait { ..some method } object MyTrait { implicit def innerObj(o:MixTest) = o.obj def ::(o:Test) = new MixTest(o) final class MixTest private[MyTrait](obj:Test) extends MyTrait } //then you can use it val a = new Test val b = a :: MyTrait b.doSomething bf // for your example val o = DBHelper.loadMyEntityFromDB(primaryKey) :: MyTrait o.doSomething 
+5
09 Oct '10 at 9:24 a.m.
source share

What about an implicit class? It seems easier for me compared to other answers with the final inner class and the "mixin" function.

 trait MyTrait { def traitFunction = println("trait function executed") } class MyClass { /** * This inner class must be in scope wherever an instance of MyClass * should be used as an instance of MyTrait. Depending on where you place * and use the implicit class you must import it into scope with * "import mypackacke.MyImplictClassLocation" or * "import mypackage.MyImplicitClassLocation._" or no import at all if * the implicit class is already in scope. * * Depending on the visibility and location of use this implicit class an * be placed inside the trait to mixin, inside the instances class, * inside the instances class' companion object or somewhere where you * use or call the class' instance with as the trait. Probably the * implicit class can even reside inside a package object. It also can be * declared private to reduce visibility. It all depends on the structure * of your API. */ implicit class MyImplicitClass(instance: MyClass) extends MyTrait /** * Usage */ new MyClass().traitFunction } 
+1
Jul 22 '16 at 11:29
source share



All Articles