这:
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类型系统的误解,我会很感激。
提前致谢。
答案 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中的泛型不具体化,因此您必须使用类标记机制来解决它。