0
votes

I am using Akka for actor model programming with Scala, and in order to fully and sufficiently use some features of my structure, I decided to use an implicit conversion from a Scala abstract class to an Akka ActorRef. It goes something like this:

abstract class A {
   val actor = system.actorOf(Props(new C),"dummy")
   def send(msg: String) = actor ! msg // This compiles fine
}

class C extends akka.actor.Actor {
   def receive = {case msg => println(msg)}
}

implicit def AtoC(a:  A) = a.actor

Then I use it this way:

class D extends A

val d = new D

Normally, and since the conversion works fine, I should be able to send a message to the actor in D just by doing this:

d ! message // This does not compile

But It's not allowed apparently, This is not a big problem since I can still use the tell method:

d.tell(message)

I can still use the "!" by using this conversion instead:

implicit def AtoC(a:  A) = a.actor.asInstanceOf[ScalaActorRef]

But, if I do this I won't be able to use any ActorRef method. I can live with not being able to use "!" but I would like to understand why a conversion causes such a behavior, or am I missing something?

Thank you!

1

1 Answers

2
votes

Because Scala doesn't do multiple implicit conversions. ! is an implicit conversion from ActorRef to ScalaActorRef (to hide symbolic methods from Java API):

/**
 * This trait represents the Scala Actor API
 * There are implicit conversions in ../actor/Implicits.scala
 * from ActorRef -> ScalaActorRef and back
 */
trait ScalaActorRef { ref: ActorRef ⇒

  /**
   * Sends a one-way asynchronous message. E.g. fire-and-forget semantics.
   * <p/>
   *
   * If invoked from within an actor then the actor reference is implicitly passed on as the implicit 'sender' argument.
   * <p/>
   *
   * This actor 'sender' reference is then available in the receiving actor in the 'sender' member variable,
   * if invoked from within an Actor. If not then no sender is available.
   * <pre>
   *   actor ! message
   * </pre>
   * <p/>
   */
  def !(message: Any)(implicit sender: ActorRef = null): Unit

}