2014-10-29 133 views
1

我試圖寫一些功能,根據輸入類型做不同的事情。 例如,我這樣做:斯卡拉鑄造仿製藥的麻煩

def Foo[T](inList: List[String]): ArrayBuffer[T] = { 
    val out: ArrayBuffer[T] = new ArrayBuffer[T]() 
    inList.map (x => { 
    val str = x.substring(1) 
    out += str.asInstanceOf[T] 
    }) 
    out 
} 

但如果我調用該函數與Foo[Long](new List("123","2342")),我得到一個ArrayBufferString S,不Long秒。對不起我的noob問題,我想了解scala和泛型。

+0

你在REPL檢查你的代碼?一切都很美好。 'scala.collection.mutable.ArrayBuffer [Long] = ArrayBuffer(23,342)' – 2014-10-29 08:35:44

+0

不知道目標是什麼,但鑄造正在打破類型安全。 – cchantep 2014-10-29 08:44:33

+0

你的'ArrayBuffer'對你來說沒有太大的幫助。爲什麼不直接返回列表中的映射結果(使用答案中提到的其中一個轉換器函數)? – acjay 2014-10-29 10:35:09

回答

4
  1. 斯卡拉運行ontop的JVM的,不知道什麼泛型和具體類型的一般不是在運行時可用。

這樣,運行時間相當於你的代碼看起來像

def Foo(inList: List[String]): (ArrayBuffer[Object]) = { 
    val out: ArrayBuffer[Object] = new ArrayBuffer[Object]() 
    inList.map (x => { 
     val str=x.substring(1) 
     out += str.asInstanceOf[Object] 
    }) 
    (out) 
    } 
  • asInstanceOf不會字符串轉換爲多頭,相反,它會拋出約不兼容類型的異常。相反,您應該爲您的函數提供從字符串到另一種類型的轉換。
  • 總而言之,你的代碼應該是這樣的:

    import scala.collection.mutable.ArrayBuffer 
    
        // here we define how convert string to longs 
        implicit def stringToLong(s: String) = s.toLong 
    
        // now this function requires to have converter from string to T in context 
        def Foo[T](inList: List[String])(implicit f: (String) => T): (ArrayBuffer[T]) = { 
        val out: ArrayBuffer[T] = new ArrayBuffer[T]() 
        inList.map { x => 
         val str = x.substring(1) 
         out += f(str) // here we apply converter 
        } 
        out 
        } 
    
        // when function is called, appropriate implicit converter from context will be used 
        Foo[Long](List("51", "42")) 
    
    1

    String投射到Long不會使其變長,但這是一個錯誤,所以您應該得到一個運行時錯誤,指出您無法將字符串轉換爲長整型。由於T沒有限制它的可能性,因此不能指望調用任何不在所有對象上的方法(例如toString)。你可以提供該功能你自己(這幾乎是地圖的準確簽名,所以你可以只使用):

    def convert[T](in: List[String])(convert: String => T): List[T] = 
        in.map(convert) 
    

    ,或者確保對象是一個類型的,你知道的方法(使用類型約束):

    trait CanConvertTo[T] { 
        def convert: T 
    } 
    
    case class Example(value: String) extends CanConvertTo[Long] { 
        def convert = value.toLong 
    } 
    
    def convert[T](in: List[CanConvertTo[T]]): List[T] = in.map(_.convert)