2016-12-05 104 views
0

我想創建一個從ClassTag到MyHelperClass [該類]的scala中的地圖,像這樣(它不編譯,因爲地圖不支持這種元素方式匹配):從一個類映射到一個匹配的通用

import scala.reflect._ 
import scala.reflect.runtime.universe._ 

val MAP_CONSTANT = map[ClassTag[T], MyHelperClass[T]](
    classTag[SomeClass] -> helperForSomeClass, 
    classTag[AnotherClass] -> helperForAnotherClass, 
) 

有沒有一種很好的方法來做到這一點?我需要編譯器知道返回的幫助程序是與輸入類標記相同的類的通用類。

我寧願不做與之匹配的幾起案件,因爲

  • 這將是醜陋的代碼
  • 這將是很難建立在這樣的代碼沒有信心同樣醜陋的測試
  • 比賽迭代檢查每個條件,這可能很慢,許多可能的幫手

回答

0

這被稱爲typeclass並更優雅地解決上下文邊界和隱式參數。

trait MyHelperClass[T] { 
    def takeOverTheWorld: Unit = .. 
} 
object MyHelperClass { 
    def apply[T : MyHelperClass]: MyHelperClass[T] = implicitly[MyHelperClass[T]] 
} 

現在,所有你需要做的就是定義一堆幫手:爲def x[T]()(implicit ev: MyHelperClass[T])

+0

這看起來非常有前途的

class X class Y object Helpers { implicit object XHelper extends MyClassHelper[X] { override def takeOverTheWorld: Unit = println("Hey I'm X") } implicit object YHelper extends MyClassHelper[Y] { override def takeOverTheWorld: Unit = println("Hey I'm actually an Y") } def doAction[T : MyHelperClass]: Unit = MyHelperClass[T].takeOverTheWorld doAction[X] // will print "Hey I'm an X" doAction[Y] // will print "Hey I'm actually an Y" } 

def x[T : MyHelperClass]是簡寫語法,但我有麻煩它工作。具體來說,我有一個通用的任何類型的T: 'process [T](data:Seq [T])(隱式幫手:MyHelperClass [T]):...' 我想拋出運行時if T不匹配助手,但我不能編譯: '無法找到隱式值的參數助手:com ... MyHelperClass [_ $ 1]' – mwlon

+0

@mwlon爲什麼你會喜歡運行時間超過編譯時間?從代碼質量的角度來看,這毫無意義,我寧願早點知道「我錯了」。如果用戶想爲一個給定類型'T'實現一個'MyHelperClass',那麼他們可以簡單地'隱式對象bla自己擴展MyHelperClass [T]',所以你不能阻止人們添加幫助者,如果你所關心的。任何其他理由偏好運行時? – flavian

+0

假設我有一個X和Y的序列,並且希望將相應的隱式幫助應用於每個隱式幫助。如果我試圖做 'val entries = Seq [_](new X(),new Y()); entries.foreach(entry => Helpers.doAction(entry))'我得到相同的錯誤。我怎樣才能強制執行所有條目可以隱式轉換爲MyHelperClass的約束呢? – mwlon