2017-02-17 36 views
3

假設我有一個集轉換爲字符串的,作爲一個Type類:獲得運行時類型拿起隱式證據

import scala.reflect.runtime.universe._ 

abstract class ToStringConverter[T] { 
    def convert(value: T): String 
} 
implicit object IntToStringConverter extends ToStringConverter[Int] { 
    def convert(value: Int) = value.toString 
} 
implicit object DoubleStringConverter extends ToStringConverter[Double] { 
    def convert(value: Double) = value.toString 
} 

和使用該類型的信息挑選合適的轉換器轉換方法:

def convert[T](v: T)(implicit ev: ToStringConverter[T]): String = ev.convert(v) 

這工作得很好。如果我有具體類型提前,例如:

scala> convert[Double](12.2) 
res0: String = 12.2 

scala> convert[Int](12) 
res1: String = 12 

是否有可能使用上面的轉換方法和運行時類型,例如,類型't'在下面?

scala> val t = typeOf[Double] 
t: reflect.runtime.universe.Type = Double 
+0

你的'convert'需要一個值作爲參數 - 你想用't'做什麼?如果你想調用'convert(t)',你可以很容易地提供'隱式對象RTUStringConverter extends ToStringConverter [runtime.universe.Type]'。 – Suma

+0

convert方法當前需要一個類型參數,並且此類型用於通過隱式機制將正確的轉換器引入到範圍中。 有時我不知道類型提前,我只有一個代表它的類型,所以我應該更改簽名傳入Type實例,並手動獲取該類型的隱式轉換器? – gnf

+0

你想以類似'val a:Any; convert [t](a)'的方式調用它? – Suma

回答

2

如果你想要做的分辨率運行時,需要反思,因爲implicits都解決了編譯時間。像這樣的代碼應該做的工作:

import scala.reflect.runtime.universe._ 

abstract class ToStringConverterAny { 
    def convertAny(value: Any): String 
} 

abstract class ToStringConverter[T] extends ToStringConverterAny { 
    def convertAny(value: Any): String = convert(value.asInstanceOf[T]) 
    def convert(value: T): String 
} 
implicit object IntToStringConverter extends ToStringConverter[Int] { 
    def convert(value: Int) = value.toString 
} 
implicit object DoubleStringConverter extends ToStringConverter[Double] { 
    def convert(value: Double) = value.toString 
} 

val converters: Map[Type, ToStringConverterAny] = Map(
    typeOf[Int] -> IntToStringConverter, 
    typeOf[Double] -> DoubleStringConverter 
) 

def convert(t: Type, v: Any) = { 
    converters(t).convertAny(v) 
} 

def convert[T](v: T)(implicit ev: ToStringConverter[T]): String = ev.convert(v) 

convert[Double](12.2) 

convert[Int](12) 

val t = typeOf[Double] 
val v: Any = 1.23 

convert(t, v) 

如果你想建立converters地圖自動,你也可以使用這種反映,但列舉派生類需要令人驚訝的不平凡的代碼(包括類加載器 - 這是當你考慮它時可以理解)。

如果您可以使ToStringConverterAny密封,則枚舉其宏中的子類應該會更容易一些。

+0

這工作正常,但我想知道(如問題的標題說)如果我可以通過隱式機制獲得轉換器而不是有一個Map,我猜不是 – gnf

+0

implicits只是編譯時間。你需要像運行時分派的地圖。你可以做的最大的工作就是用宏(編譯時反射)以某種方式反映暗示來建立一個地圖編譯時間。 – Suma