內泛型類型我有兩個類:斯卡拉。如何推斷類繼承
class Base[A]{
def doSome:A
}
class StringImpl extends Base[String]
我怎麼可以推斷出(不清單,只反射觀)該類StringImpl內泛型類型A是一個字符串? (在現實情況下Iheritance結構可能是馬赫更復雜,例如)
內泛型類型我有兩個類:斯卡拉。如何推斷類繼承
class Base[A]{
def doSome:A
}
class StringImpl extends Base[String]
我怎麼可以推斷出(不清單,只反射觀)該類StringImpl內泛型類型A是一個字符串? (在現實情況下Iheritance結構可能是馬赫更復雜,例如)
使用Scala的運行時反射(isInstanceOf
用於擦除類型不工作 - 它總是返回true
):
typeOf[StringImpl] <:< typeOf[Base[String]] //true
typeOf[StringImpl] <:< typeOf[Base[Int]] //false
參見:http://www.scala-lang.org/api/2.11.7/scala-reflect/#scala.reflect.api.Types $ TypeApi
val tp = typeOf[StringImpl]
tp.baseType(tp.baseClasses(1)).typeArgs
res17_4: List[reflect.runtime.package.universe.Type] = List(String)
它允許您訪問類型參數等更復雜的情況。
更新。爲ClassSymbol
您可以使用typeSignature
方法:
tp.typeSymbol.typeSignature
res19_5: reflect.runtime.package.universe.Type = Helper.this.Base[String] {
def <init>(): Helper.this.StringImpl
def doSome: String
}
此外,宏(如果你不想明顯WeakTypeTag
溶液):
import c.universe._
val TypeApply(_, List(typeTree)) = c.macroApplication
//you can analyze typeTree here
Scala: Get type name without runtime reflection and without type instance
一般的回答
泛型類型被擦除因此在運行時默認情況下不存儲信息 - 一般情況下,在物理上不可能在運行時獲得擦除類型(沒有ClassTag/TypeTag)(如果存在這種情況,您只能在子類中探索方法/成員簽名)。但是,你總是可以做編譯時檢查,是這樣的:
abstract class Base{
type A
def doSome:A
}
class StringImpl extends Base{
type A = String
def doSome:A = "aaa"
}
implicitly[StringImpl#A =:= String]
我認爲你可以得到doSome
方法返回類型爲泛型類型一個沒有清單(對於沒有訪問權限到父類),如:
new StringImpl().getClass.getMethod("doSome").getReturnType.getSimpleName
> String
感謝您的回答。但是我在宏黑盒子上下文中工作,在這些時候方法是不可訪問的,只有Base.doSome的MethodSymbol和純泛型類型A. –
類型的直接位置被擦除,但在聲明的類的水平類型聲明保持。如果按類分析繼承類中的類型替換,則可以計算類型或其下限。我在java反射中使用了這種方法,我想也許有些東西已經準備好用於scala反射或宏/工具箱API。 –
@RomanYurin我用'typeOf [StringImpl] <:
dk14
它在編譯時使用顯式代碼,但不使用反射符號。我的任務中有StringImpl作爲ClassSymbol。 (我開發代碼分析工具) –