2017-08-15 66 views
-1

此:Scala的参数化方法使用参数通用类无法

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

未能编译,因为编译器不能在第二应用方法解决T,R或S。

关于这个例子的注意事项:我已经拿出了所有的函数体来使其具有最小的可重复性。如果R不是字符串,此示例将失败。如果任何人有兴趣,我试图做的是为有限形式的安卡阿卡演员制作一个结构。这个想法是,SimpleJob可以被子类化和参数化,然后消息传递给所有的子类actor,并通过调用形式为SimpleJob [ActorSubclassType] .apply(message)的对象来传递,其中参数和返回值将是type -安全。 apply方法是检查给定类的actor是否已经实例化,如果没有,则创建它,然后传递该消息并返回Future作为答复。事实证明,由于多种原因,这是不可行的,但是沿途我意识到有些东西我不了解scala的内嵌系统,我试图找出那些是什么,所以我不会类似兔子洞再次。

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

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

它编译,但我希望能够只用一个类型参数的功能,因为它彻底解决了其他类型。

如果有人能帮助我理解我对scala的类型系统显然存在误解,我将不胜感激。

在此先感谢。

+0

'dostuff [T]'从'SimpleJob'投影'T'类型参数 – cchantep

+0

是的......故意的。但那又如何?未能编译的部分是对象,并且在这个最小可重现的示例中,我已经消除了依赖于特征方法的对象应用方法中的任何引用。 – Bob

+0

你的例子没有太大意义。 'S.getClass'是不可能的,因为'S'只是类型的_name_。你不能'String.getClass',可以吗? '.getClass'是一个实例方法:你必须有一个'S'实例来调用'.getClass'。 '“做东西”.asInstanceOf [R]'也没有任何意义:如果'R'不是字符串,它会崩溃。有一个参数没有意义,只能有一个值。 我明白了,你的意思是为了举例简化它,但看起来你走得太远了:它并没有解释你实际上试图做什么 – Dima

回答

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中的泛型不具体化,因此您必须使用类标记机制来解决它。

+0

谢谢!我认为这是通向解决方案的途径,并且你已经解释了我缺少的一些东西。但是---我真的希望在SimpleJob特征的参数化中包含T和R,因为我想定义参数化SimpleJob的类。所以我想有一个扩展SimpleJob [Int,String]的DumbJob,最终的结果是,如果我调用SimpleJob.apply [DumbJob](),参数和返回值分别强类型为Int和String 。有什么建议么?再次感谢! – Bob

+0

您仍然需要重写扩展类中的类型成员,所以如果您执行类似于'class DumbJob extends SimpleJob {override type T = Int;重写类型R = String}'那么你会得到你所要求的。 –