How to mix-in a trait to instance?

前端 未结 5 1390
日久生厌
日久生厌 2020-12-04 12:04

Given a trait MyTrait:

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

it can be mixed into a class with extends<

5条回答
  •  南方客
    南方客 (楼主)
    2020-12-04 12:49

    I have a idea for this usage:

    //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 trait as below:

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

    for your example code:

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

    I hope this can help 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 pattern has some restrict, you can't use some implicit helper method that defined already.

    val a = new Test
    a.f
    val b = a :: AnyTrait
    b.f1
    b.f
    val c = "say hello to %s" :: AnyTrait
    println(c.intern)  // you can invoke String's method 
    println(c.format("MyTrait"))  //WRONG. you can't invoke StringLike's 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
    

提交回复
热议问题