scala,结构细化中的参数类型

时间:2014-08-27 02:54:57

标签: scala akka

当我使用Scala 2.11.1和Akka 2.3.4编译以下代码时,我得到错误:

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={
                              ^

代码:

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])
  }
}

我将myTrait定义为myTrait [T&lt ;:myTrait [T]]的原因是我想要myTrait的子类可以用子类参数覆盖computeDistance方法。遵循此post

otherClass提供了一个方法func,用于在myClass实例列表上生成一些计算。 (实际上上面的代码是我需要的抽象。)

在行为上添加泛型类型可以消除上述错误,但会导致新的错误。

def behavior[S](list: List[T], ele: S):Receive={
  case _ =>
    sender ! Job(list.head, ele)
    context become behavior(list.tail, ele)
}

然后,在Job(list.head,ele)中,类型S的元素不匹配类型为T。

如何解决这个问题?

3 个答案:

答案 0 :(得分:4)

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]
  }
}

通过将其作为新类包装

来获取structural actor的创建

答案 1 :(得分:3)

添加类型注释以将类型扩展为普通Actor可解决问题:

system.actorOf(Props(new Actor{
    // ...
}: Actor))

答案 2 :(得分:1)

为行为方法添加泛型类型:

def behavior[T](map: HashMap[Int, List[T]], list: List[(T, Int)], ele: T):Receive={
    case _ =>
}

https://issues.scala-lang.org/browse/SI-1906 由于在运行时缺少类型信息,因此无法使用结构类型外定义的抽象类型。 请检查此答案Using Scala structural types with abstract types