When I compile following code with Scala 2.11.1 and Akka 2.3.4, I get Error:
Error:(24, 35) Parameter type in structural refinement may not refer to an abstract type defined outside that refinement
def behavior(list: List[T], ele: T):Receive={
^
Error:(24, 35) Parameter type in structural refinement may not refer to a type member of that refinement
def behavior(list: List[T], ele: T):Receive={
^
The code:
package exp
import akka.actor.{ActorSystem, Props, Actor}
trait myTrait[T <: myTrait[T]]{
def computeDistance(that: T): Double
}
class otherClass[T <: myTrait[T]](){
def func(data: List[T]):List[String]={
val system = ActorSystem()
system.actorOf(Props(new Actor{
case object START
case class Job(e1: T, e2: T)
def receive = {
case START =>
context become behavior(data.tail, data.head)
}
def behavior(list: List[T], ele: T):Receive={
case _ =>
sender ! Job(list.head, ele)
context become behavior(list.tail, ele)
}
}))
List.empty[String]
}
}
object Test {
class myClass(val x:Double) extends myTrait[myClass]{
override def computeDistance(that: myClass): Double = this.x - that.x
}
def main(args: Array[String]){
val fc = new otherClass[myClass]()
fc.func(List.empty[myClass])
}
}
The reason I define myTrait as myTrait[T <: myTrait[T]] is that I want subclass of myTrait can override computeDistance method with subclass argument. Follows this post.
otherClass provides a method func to produce some computation on a list of myClass instances. (Actually the above code is an abstraction of my need.)
Adding generic type on behavior can eliminate the above error, but it will cause new error.
def behavior[S](list: List[T], ele: S):Receive={
case _ =>
sender ! Job(list.head, ele)
context become behavior(list.tail, ele)
}
Then, in Job(list.head, ele), the ele of type S mismatches type T.
How to solve this problem?
Adding a type annotation to widen the type to plain Actor fixes the problem:
system.actorOf(Props(new Actor{
// ...
}: Actor))
class otherClass[T <: myTrait[T]](){
def func(data: List[T]):List[String]={
val system = ActorSystem()
class FooActor extends Actor {
case object START
case class Job(e1: T, e2: T)
def receive = {
case START =>
context become behavior(data.tail, data.head)
}
def behavior(list: List[T], ele: T):Receive={
case _ =>
sender ! Job(list.head, ele)
context become behavior(list.tail, ele)
}
}
system.actorOf(Props(new FooActor))
List.empty[String]
}
}
Just get ride of that structural actor creation by wrapping it as a new class
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With