你想做的事情有點棘手。如你所見,子類型不會得到你想要的,因爲必須返回所有返回類型的超類型。
雖然輸入變量,可能會挽救一天!
def convertType[T](x: String): T = x.asInstanceOf[T]
但是,這不是你所需的東西......你需要的東西,有基於什麼T
被傳遞不同的行爲。喜歡的東西(不是真正的Scala)
def convertType[T](x: String): T = T match {
case Double => x.toDouble
case Int => x.toInt
// And all your other cases
}
不幸的是Scala是不是一個完整的依賴性類型的語言,所以我們沒有,可以直接在類型的行爲,所以那場比賽語句不工作的功能。
但是,如果我們爲T
類型提供了價值級「見證」,也許我們可以逃避我們的轉換。
def convertType[T](x: String)(witness: T): T = witness match {
case _: Double => x.toDouble
case _: Int => x.toInt
// Fill in other cases as necessary
}
我們可以把這個稍微爲自己方便的通過使證人implicit
。現在只能讓我們在中途停下來,因爲我們仍然需要擁有奇怪的虛擬隱式值,除了作爲我們功能的證據外(例如隨機我們需要類似implicit val z = 2
),我們不需要做任何事情。
我們可以擺脫創建這些虛擬值來傳入證人的需求嗎?
是的,有兩種方法。一種是使用Scala的TypeTags,它們確實是編譯器自動生成的類型的值級目擊者。
import scala.reflect.runtime.universe._
def convertTypes[T](x: String)(implicit witness: TypeTag[T]): T = witness match {
case a if a =:= typeOf[Int] => x.toInt
case a if a =:= typeOf[Double] => x.toDouble
}
或者,您可以將實際轉換移出到單獨的特徵並讓目擊者執行特徵指定的行爲。
trait Convertable[T] {
def convertFromString(x: String): T
}
implicit object ConvertInt extends Convertable[Int] {
override def convertFromString(x: String): Int = x.toInt
}
// Do the same for your other types
def convertType[T](x: String)(implicit witness: Convertable[T]): T = witness.convertFromString(x)
我們走吧!一個很好的類型安全ish轉換方法(至少這是最後一個)。如果您傳遞格式不正確的字符串,您可能希望將整個事件包裝在scala.util.Try
中。
順便說一下,我們剛剛重新創建了typeclasses(或者使用了Scala的內置TypeTag
類型類)。
爲什麼不使用泛型? –