首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Akka接收方法中在Scala中组合特征行为

在Akka接收方法中在Scala中组合特征行为
EN

Stack Overflow用户
提问于 2011-12-31 00:11:32
回答 2查看 4.5K关注 0票数 20

考虑以下两个特征:

代码语言:javascript
运行
复制
trait Poked extends Actor {
  override def receive = {
    case Poke(port, x) => ReceivePoke(port, x)
  }

  def ReceivePoke(port: String, x: Any)
}

trait Peeked extends Actor {
  override def receive = {
    case Peek(port) => ReceivePeek(port)
  }

  def ReceivePeek(port: String)
}

现在考虑我可以创建一个新的Actor来实现这两个特征:

代码语言:javascript
运行
复制
val peekedpoked = actorRef(new Actor extends Poked with Peeked)

如何编写接收处理程序?也就是说,接收器应该类似于下面的代码,尽管是“自动生成的”(即所有特征都应该组合在一起):

代码语言:javascript
运行
复制
def receive = (Poked.receive: Receive) orElse (Peeked.receive: Receive) orElse ...
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-12-31 03:53:18

您可以使用super[T]来引用特定超类/特征的成员。

例如:

代码语言:javascript
运行
复制
trait IntActor extends Actor {
    def receive = {
        case i: Int => println("Int!")
    }
}

trait StringActor extends Actor {
    def receive = {
        case s: String => println("String!")
    }
}

class IntOrString extends Actor with IntActor with StringActor {
    override def receive = super[IntActor].receive orElse super[StringActor].receive
}

val a = actorOf[IntOrString].start
a ! 5 //prints Int!
a ! "Hello" //prints String!

编辑:

为了回应Hugo的评论,这里有一个解决方案,允许您在不必手动连接它们的接收器的情况下组合mixins。从本质上讲,它涉及一个具有可变List[Receive]的基本特征,每个混合特征调用一个方法将其自己的接收添加到列表中。

代码语言:javascript
运行
复制
trait ComposableActor extends Actor {
  private var receives: List[Receive] = List()
  protected def registerReceive(receive: Receive) {
    receives = receive :: receives
  }

  def receive = receives reduce {_ orElse _}
}

trait IntActor extends ComposableActor {
  registerReceive {
    case i: Int => println("Int!")
  }
}

trait StringActor extends ComposableActor {
  registerReceive {
    case s: String => println("String!")
  }
}

val a = actorOf(new ComposableActor with IntActor with StringActor).start
a ! 5 //prints Int!
a ! "test" //prints String!

唯一要记住的是,接收的顺序不应该是重要的,因为你不能很容易地预测哪个是链中的第一个,尽管你可以使用一个可变的hashmap而不是一个列表来解决这个问题。

票数 28
EN

Stack Overflow用户

发布于 2012-01-02 02:11:22

您可以在基本执行元类中使用空接收,在其定义中使用链接收。Akka 2.0-M2示例:

代码语言:javascript
运行
复制
import akka.actor.Actor
import akka.actor.Props
import akka.event.Logging
import akka.actor.ActorSystem

class Logger extends Actor {
  val log = Logging(context.system, this)

  override def receive = new Receive {
    def apply(any: Any) = {}
    def isDefinedAt(any: Any) = false
  }
}

trait Errors extends Logger {
  override def receive = super.receive orElse {
    case "error" => log.info("received error")
  }
}

trait Warns extends Logger {
  override def receive = super.receive orElse {
    case "warn" => log.info("received warn")
  }
}

object Main extends App {
  val system = ActorSystem("mysystem")
  val actor = system.actorOf(Props(new Logger with Errors with Warns), name = "logger")
  actor ! "error"
  actor ! "warn"
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8681444

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档