【问题标题】:Reduce code duplication by abstracting mixing class通过抽象混合类减少代码重复
【发布时间】:2013-06-24 13:24:32
【问题描述】:

我必须创建类似于这种形式的演员类:

class ActorSupervisorOne(prop: Prop) extends Actor {
  val dbSuper = context.actorOf(prop)
  val subActor = context.actorOf(Props(new SubActorClass(dbSuper) with **SomeHandlersOne**))

  def receive = {
    case msg =>
      subActor forward msg
  }
}

class ActorSupervisorTwo(prop: Prop) extends Actor {
  val dbSuper = context.actorOf(prop)
  val subActor = context.actorOf(Props(new SubActorClass(dbSuper) with **SomeHandlersTwo**))

  def receive = {
    case msg =>
      subActor forward msg
  }
}

他们之间唯一的区别在于混合特性。用类型参数抽象它或抽象类型成员将不起作用。我尝试了以下解决方案,但它看起来很难看,并且仍然有代码重复:

abstract class Super extends Actor {
  _: {
    val handler: Props
  } =>

  lazy val actor = context.actorOf(handler)

  def receive = {
    case msg =>
      actor forward msg
  }

}

class ActorSupervisorOne(val dbSuper: ActorRef) extends Super {
  val handler = Props(new SubActorClass(dbSuper) with SomeHandlersOne)
  actor
}

class ActorSupervisorTwo(val dbSuper: ActorRef) extends Super {
  val handler = Props(new SubActorClass(dbSuper) with SomeHandlersTwo)
  actor
}

但在这种情况下,我必须调用 actor 来正确初始化它,否则它将无法正常工作。有没有其他解决方案可以减少这种情况?

【问题讨论】:

    标签: scala inheritance abstraction code-duplication


    【解决方案1】:

    您可以在运行时使用反射来选择SomeHandlersXYZ,但如果您不想诉诸反射,那么我认为没有一种方法可以在不复制子角色的情况下实现您想要的实例化代码(请参阅我的this answer 以获得解释)。您可以通过以下方式(草图)进行操作,基本上传入一个工厂函数:

    class ActorSupervisor(prop: Prop, getSubActor: Actor => SubActorClass) extends Actor {
      val dbSuper = context.actorOf(prop)
      val subActor = context.actorOf(Props(getSubActor(dbSuper)))
    
      def receive = {
        case msg =>
          subActor forward msg
      }
    }
    
    val asOne = new ActorSupervisor(..., a => new SubActorClass(a) with SomeHandlersOne)
    val asTwo = new ActorSupervisor(..., a => new SubActorClass(a) with SomeHandlersTwo)
    

    【讨论】:

      【解决方案2】:

      这个解决方案怎么样:

      class ActorSupervisor(subActor: => Actor) extends Actor {
        val actor = context.actorOf(Props(statsProps))
        def receive = {
          case msg =>
            actor forward msg
        }
      }
      

      然后,就像在 Malte Schwerhoff 中一样,您可以像这样创建新演员:

      val first = new ActorSupervisor(new SubActorClass(...) with SomeHandlersOne)
      

      我认为使用宏可以实现更优雅的解决方案,但我不擅长它们

      【讨论】:

        【解决方案3】:

        您可以通过 onReceive 传递冰球。

        class ClassMixed(params: Options*)
            extends BaseClass(params: _*)
            with Mixin {
        
          override def receive =
            mixinReceive orElse receive
        }
        

        其中 Mixin 有一个名为 mixinReceive 的方法,并且 BaseClass 覆盖了接收

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-09-30
          • 2016-07-24
          • 1970-01-01
          相关资源
          最近更新 更多