6

I'm using the Akka actors library here. The actors library defines a partial function "receive" which an actor that extends "actor" must implement to deal with various messages. I am creating a trait hierarchy for my application where trait "clockActor" extends Actor and "MasterClock" and "SubClock" extend "clockActor". I'm looking to add the common functionality of clocks in to the "clock" trait's receive function but then how to I add extra functionality to the receive function in the master and sub clock traits?

In short, I need a way to add extra case statements to a partial function. Ideas?

tshepang
  • 12,111
  • 21
  • 91
  • 136
Alex
  • 650
  • 9
  • 23
  • 2
    You can compose partial functions with [`orElse`](http://www.scala-lang.org/api/current/index.html#scala.PartialFunction). Would it do the trick? – 4e6 Jan 09 '13 at 14:38
  • Not really. The akka library does all it's message stuff by calling receive internally so I cant get in there an append an orElse to the call. – Alex Jan 09 '13 at 14:49
  • in fact, yes, orElse does exactly what I need. Sloppy googling and only picking the first result made it look different but I've got it working now. – Alex Jan 09 '13 at 15:17

2 Answers2

14

As already suggested, you could easily compose PartialFunctions using orElse

trait ClockActor {

    def commonOp = {
        case ... => ...
    }

}

class MasterClock extends Actor with ClockActor {

    def receive = commonOp orElse masterOp

    def masterOp = {
        case ... =>  ...
    }

}

class SubClock extends Actor with ClockActor {

    def receive = commonOp orElse subOp

    def subOp = {
        case ... =>  ...
    }

}
pagoda_5b
  • 7,333
  • 1
  • 27
  • 40
1

One thing that comes to mind is to do something like this:

trait ClockActor {
  def pf:PartialFunction[String, Boolean] = {
    case "a" => true
    case v if(_pf.isDefinedAt(v)) => _pf.apply(v)
  }

  def _pf:PartialFunction[String, Boolean] = Map.empty
}

object MasterClock extends ClockActor {

  override def _pf:PartialFunction[String, Boolean] = {
    case "b" => false
  }

  println(pf("a"))
  println(pf("b"))

}

which will output:

scala> MasterClock
true
false

The value true comes from the definition in the partial function of the Trait ClockActor, the falsecomes from the Object MasterClock.

jcern
  • 7,798
  • 4
  • 39
  • 47
  • Yea this works. I seemed to have the idea that when you "override" a function then you cant touch the original. If I have to then I will use this way of doing things but I'm looking more for a way that people who are implementing the subclasses don't have to care about calling super or any implementation in the parent trait. – Alex Jan 09 '13 at 14:47
  • @Alex, I made a quick edit which might help more with what you are looking to accomplish. I changed the trait to have two functions, one `pf` which would be public and the `_pf` which is by default empty and would be overridden in the class as necessary. It is essentially the same as what I had before, but this way the user does not need to worry about calling super since the public calls would be to the `pf` function of the trait. – jcern Jan 09 '13 at 15:07
  • Got a version working but a completely different way. `class MasterNode extends treeNode { def masterReceive:Receive = { case "specificBehaviour" => {println("I am behaving like a master")} } override def receive = masterReceive orElse super.receive } ` Where receive is the method I am forced to implement in the parent trait and I just create a new partial function for the new behaviour in the subclass and chain them with orElse. – Alex Jan 09 '13 at 15:18