2017-08-15 67 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}'那麼你會得到你所要求的。 –