2017-07-25 118 views
0

內泛型類型我有兩個類:斯卡拉。如何推斷類繼承

class Base[A]{ 
    def doSome:A 
} 

class StringImpl extends Base[String] 

我怎麼可以推斷出(不清單,只反射觀)該類StringImpl內泛型類型A是一個字符串? (在現實情況下Iheritance結構可能是馬赫更復雜,例如)

回答

2

使用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] 
+0

類型的直接位置被擦除,但在聲明的類的水平類型聲明保持。如果按類分析繼承類中的類型替換,則可以計算類型或其下限。我在java反射中使用了這種方法,我想也許有些東西已經準備好用於scala反射或宏/工具箱API。 –

+0

@RomanYurin我用'typeOf [StringImpl] <: dk14

+0

它在編譯時使用顯式代碼,但不使用反射符號。我的任務中有StringImpl作爲ClassSymbol。 (我開發代碼分析工具) –

0

我認爲你可以得到doSome方法返回類型爲泛型類型一個沒有清單(對於沒有訪問權限到類),如:

new StringImpl().getClass.getMethod("doSome").getReturnType.getSimpleName 
> String 
+0

感謝您的回答。但是我在宏黑盒子上下文中工作,在這些時候方法是不可訪問的,只有Base.doSome的MethodSymbol和純泛型類型A. –