我们如何覆盖scala actor的反应结构?

时间:2012-11-14 22:55:50

标签: scala remote-actors act

检测scala actor中收到的消息类型的常用方法是

loop{
     react{
            case x: String =>
           }
     }

但是,我想知道如何覆盖react构造的这个实现,以便我们可以对收到的消息进行隐式记录。

我正在尝试实现下面提到的用例 - >  1.在消息与任何案例类匹配之前,我想在控制台/文件上写一个日志语句,显示消息的出现。  2.我们可以通过println()/ log4j logging显式记录这些消息。但是,我想为scala actor设计一个通用记录器,它将记录发送或接收的所有消息。

这方面的任何帮助都会有所帮助。 提前致谢

2 个答案:

答案 0 :(得分:1)

首先,请注意Scala actors库已被弃用,以支持Akka。所以这个答案将不会很长时间有用(尽管其他演员库将继续有一段时间可用 - 而且如果人们想要维护它,它可能永远是开源的。)

无论如何,react方法在scala.actors.Actor中定义。根本无法导入它,或用自己的隐藏它。你自己的是什么

嗯,该方法只需PartialFunction[Any,Unit]。所以,你也应该:

def react(pf: PartialFunction[Any,Unit]): Nothing = { /*how?;*/ Actor.react(/*what?*/) }

你真的只能访问部分功能,你必须按照Actor.react来做你想做的事。因此,您需要将pf包装在执行日志记录的另一个PartialFunction中。所以你可以

val qf = new PartialFunction[Any,Unit] {
  def isDefinedAt(a: Any) = pf.isDefinedAt(a)
  def apply(a: Any): Unit = {
    log(a)  // Maybe add more logic to know what a is
    pf(a)
  }
}

如果您想查看进入并经过检查但实际上没有消费的消息,您也可以使用isDefinedAt执行更多操作。

所以,显然,我希望/*how?*/是上面定义(创建)qf,而/*what?*/只是qf

如果你想知道a是否是一个案例类,答案是你不能(按设计)。案例类只是普通Scala特性之上的语法糖;它只是为了节省你打字。例如,请参阅this question

但是,您可以通过Product的模式匹配得到非常接近,并检查它是否有copy方法:

case class M(i: Int)
val a: Any = M(5)

scala> a match {
  case p: Product if p.getClass.getMethods.exists(_.getName=="copy") => println("Yes")
  case _ => println("No")
}
Yes

如果您真的想要获得幻想,请检查copy是否与构造函数具有相同数量和类型的参数。

答案 1 :(得分:1)

//Following is a code for a logReact Method that does the same thing as react but also logs the message received hope this works for you
import scala.actors.Actor;
import scala.actors.Actor._

trait ActorLogging extends Actor {
    def logReact(handler: PartialFunction[Any, Unit]): Nothing = {
        val handler2: PartialFunction[Any, Unit] = {
            case x =>
                println("Inside Logs -- with message recieved  -- " + x.toString);
                handler.apply(x);
        }
        super.react(handler2)
    }
}

class sumAct extends Actor with ActorLogging {
    def act() {
        loop {
            logReact {
                case a: Int =>
                    println("Inside actor Sum Act Received the message -- " + a)
                    exit;
            }
        }
    }
}

object ActorLog {
    def main(args: Array[String]): Unit = {
        var s: sumAct = new sumAct;
        s.start();
        s ! 1.toInt;
    }
}