隐式继承 - 如何删除样板和代码重复

时间:2017-12-09 16:37:45

标签: scala inheritance implicit

在下面的代码示例中,有很多代码重复。有什么办法可以删除吗?我一直在思考这个问题,但仍然不知道。

abstract class RouteBase[E <: Entity](
  )(
    implicit
    i:  ClassTag[E],
    en: Encoder[E],
    de: Decoder[E],
    sa: InterfaceToStateAccessor,
    ec: ExecutionContext)
{
   common concrete methods ...
   abstract methods ...
}

abstract class GetRouteBase [E <: Entity] (
    implicit
    i:  ClassTag[E],
    en: Encoder[E],
    de: Decoder[E],
    sa: InterfaceToStateAccessor,
    ec: ExecutionContext) extends RouteBase[E]
{
  implemented methods used by Get operations ...
}

class GetRoute[E <: Entity](
  )(
    implicit
    i:  ClassTag[E],
    en: Encoder[E],
    de: Decoder[E],
    sa: InterfaceToStateAccessor,
    ec: ExecutionContext) extends GetRouteBase[E]
   {  
     actual method implementations of all abstract methods ...  
   }
}

编辑:

有趣的是,这段代码编译得很好:

class A {
  implicit val s:String = "bla"
}
class B  extends  A
{
  def printImplicit(implicit s:String)={
    println(s)
  }
  printImplicit
}

2 个答案:

答案 0 :(得分:1)

您可以尝试创建聚合隐式上下文类并传递它。使用一些存根而不是实际类型,如

type Entity = Object
type MyEntity = String
trait Encoder[E] {}
trait Decoder[E] {}
trait InterfaceToStateAccessor {}

您可以创建以下内容:

@implicitNotFound("Make sure that you have implicit ClassTag, Encoder, Decoder, InterfaceToStateAccessor, and ExecutionContext visible here")
class RouteImplicitContext[E <: Entity](i: ClassTag[E],
                                               en: Encoder[E],
                                               de: Decoder[E],
                                               sa: InterfaceToStateAccessor,
                                               ec: ExecutionContext) {
  implicit val ii: ClassTag[E] = i
  implicit val ien: Encoder[E] = en
  implicit val ide: Decoder[E] = de
  implicit val isa: InterfaceToStateAccessor = sa
  implicit val iec: ExecutionContext = ec

}

object RouteImplicitContext {
  implicit def create[E <: Entity](implicit i: ClassTag[E],
                                   en: Encoder[E],
                                   de: Decoder[E],
                                   sa: InterfaceToStateAccessor,
                                   ec: ExecutionContext): RouteImplicitContext[E] = new RouteImplicitContext[E](i, en, de, sa, ec)
}

然后您可以将其用作

abstract class RouteBase[E <: Entity]()(implicit ctx: RouteImplicitContext[E]) {

  def doSomethingStrange(e: Entity)(implicit i: ClassTag[E],
                                    en: Encoder[E],
                                    de: Decoder[E],
                                    sa: InterfaceToStateAccessor,
                                    ec: ExecutionContext): Unit = {
    println(s"e = $e; implicits: i = $i, en=$en, de=$de, sa=$sa, ec=$ec")
  }

}

abstract class GetRouteBase[E <: Entity](implicit ctx: RouteImplicitContext[E]) extends RouteBase[E] {
}

class GetRoute[E <: Entity]()(implicit ctx: RouteImplicitContext[E]) extends GetRouteBase[E] {

  import ctx._ // <- this is important for code to compile

  def callSomethingStrange(e: Entity) = {
    doSomethingStrange(e)
  }
}

def test(): Unit = {
  implicit val en = new Encoder[MyEntity] {}
  implicit val de = new Decoder[MyEntity] {}
  implicit val sa = new InterfaceToStateAccessor {}
  import scala.concurrent.ExecutionContext.Implicits.global

  val gr = new GetRoute[MyEntity]()
  gr.doSomethingStrange("abc")
}

此代码编译并运行正常。

答案 1 :(得分:0)

这是我能想到的最好的。我不确定在这个例子中是否可以减少代码重复。

trait T {
  implicit val s:String
  implicit val i:Int
}

trait A { T =>
    def printA(implicit s:String) = {println("A"+s)}
}


trait B extends  A
{ T=>
  def printB(implicit i:Int) = {println("B"+i)}
}

trait C extends  B
{ T=>
  def printImplicit(implicit s:String,i:Int)={
    println(s)
    printA
    printB
  }
}

class D(implicit s2:String,i:Int) extends C {

    printImplicit
}