0

I'd like to build a convinient function for making akka actors:

 def makeActor[T](id: Int): ActorRef =
   system.actorOf(Props(classOf[T], id, updater), "entity" + id)

 makeActor[SomeActor](1) ! "Some Message"

But this says "class type required but T found". Whats wrong with this code?

Themerius
  • 1,861
  • 1
  • 19
  • 33

3 Answers3

3

Use scala reflection for this, e.g:

import scala.reflect._

def spawn[T <: Actor: ClassTag](id: Int) = system.actorOf(Props(classTag[T].runtimeClass, ...), s"entity$id")
4lex1v
  • 21,367
  • 6
  • 52
  • 86
2

An answer can be found here: Scala classOf for type parameter

You can write your code for example like this:

def makeActor[T](id: Int)(implicit ev: Manifest[T]): ActorRef = system.actorOf(Props(ev.erasure, id, updater), "entity" + id)
Community
  • 1
  • 1
Rado Buransky
  • 3,252
  • 18
  • 25
  • I used `ev.runtimeClass` because `ev.erasure` is deprecated in 2.10. I've edited your post. Thanks for this! – Themerius Mar 13 '14 at 12:10
2

Fully working example:

import akka.actor.{ActorSystem, Props, Actor, ActorRef}
import scala.reflect.ClassTag

object TestActor extends App {

  val system: ActorSystem = ActorSystem("rest-service-actor-system")

  def makeActor[T <: Actor : ClassTag](id: Int): ActorRef =
    system.actorOf(Props(implicitly[ClassTag[T]].runtimeClass), "entity" + id)

  class A extends Actor {
    override def receive = {
      case anything => println("A GOT MESSAGE: " + anything)
    }
  }

  class B extends Actor {
    override def receive = {
      case anything => println("B GOT MESSAGE: " + anything)
    }
  }

  makeActor[A](1) ! "hello"
  makeActor[A](2) ! "bye"

  system.shutdown()
}

usually prints:

A GOT MESSAGE: bye
A GOT MESSAGE: hello

It forces you to have a type that is also an Actor. For instance this code will not compile:

class C

makeActor[C](3)

error you get is:

type arguments [TestActor.C] do not conform to method makeActor's type parameter bounds [T <: akka.actor.Actor]
  makeActor[C](3)
           ^
yǝsʞǝla
  • 16,272
  • 2
  • 44
  • 65