参数化通用类参数化Scala方法失败

时间:2017-08-15 00:20:52

标签: scala oop

这:

trait SimpleJob[+T <: Serializable, +R <: Serializable]  {
  def dostuff[T](message : T) : R
}

object SimpleJob {
  def get_or_create_job(name : String) = print("do stuff")

  def apply[T, R](name : String, message : T) : Future[R] = Future{"do stuff".asInstanceOf[R]}

  def apply[S <: SimpleJob[T, R]](message : T) : Future[R] = this(classOf[S].getName, message)
}

编译失败,因为编译器无法在第二个apply方法中解析T,R或S.

关于示例的注意事项:我已经取出了所有函数体,使其具有最低的可重现性。如果R不是String,则此示例将失败。如果有人感兴趣,我试图做的是为有限形式的类型安全的Akka演员制作一个结构。想法是SimpleJob可以被子类化和参数化,然后通过调用SimpleJob [ActorSubclassType] .apply(message)形式传递给所有子类actor的消息,其中参数和返回值将是类型-安全。 apply方法是检查给定类的actor是否已经被实例化,如果没有,则创建它,然后传递消息并返回Future以进行回复。事实证明这不是可行的,原因有多种,但是我一直意识到scala的遗传系统还有一些我不了解的东西,我试图找出那是什么,所以我不会发生类似的事情。兔子洞再次出现。

如果我添加两个这样的参数:

def apply[S <: SimpleJob[T, R], T, R](message : T) : Future[R] = this(classOf[S].getName, message)

它编译,但我希望能够仅使用一种类型参数化该函数,因为它完全解析了其他类型。

如果有人能帮我理解我对scala类型系统的误解,我会很感激。

提前致谢。

1 个答案:

答案 0 :(得分:1)

问题是在def apply[T, R, S <: SimpleJob[T, R]](message: T): Future[R]中,S类型根本没有在方法参数中使用,这自然不允许编译器推断出S的具体值论证反之亦然。如果您将SimpleJob的实例传递给方法,那么情况就会相反 - 编译器可以推断出参数类型:

def apply[T, R, S <: SimpleJob[T, R]](sj: SimpleJob[T, R])
                                     (message: T): Future[R] = ???

或者,您可以使用抽象类型成员而不是类型参数:

trait SimpleJob {
  type T <: Serializable
  type R <: Serializable
  def dostuff[T](message: T) : R
}

object SimpleJob {
  def apply[S <: SimpleJob](message: S#T)(implicit sct: ClassTag[S]): Future[S#R] = 
    Future { println(sct.runtimeClass.getName); ??? }
}

请注意,classOf[S]是类型参数时,您无法使用S; JVM中的泛型不具体化,因此您必须使用类标记机制来解决它。