2015-01-16 3 views
1

Я пытаюсь проверить, соответствует ли тип возвращаемого метода заданному типу.Как фильтровать методы по типу возврата с отражением scala?

Как-то я нашел два типа строк, которые не равны.

class VarAndValue { 
    @BeanProperty 
    val value = "";  
} 

class ScalaReflectionTest { 

    @Test 
    def myTest(): Unit = { 

    val type1 = universe.typeOf[String] 

    // Get return value of VarAndValue.getValue 
    val type2 = universe.typeOf[VarAndValue]. 
     declarations. 
     filter { m => m.name.decoded == "getValue" && m.isMethod }. 
     head. 
     asInstanceOf[universe.MethodSymbol]. 
     returnType 

     println(type1) // String 
     println(type2) // String 
     println(type1.getClass()) 
     println(type2.getClass()) // !=type1.getClass() !! 
     println(type1==type2)  // False 
    } 
} 

дает ...

String 
String 
class scala.reflect.internal.Types$TypeRef$$anon$3 
class scala.reflect.internal.Types$TypeRef$$anon$6 
false 

Как я могу фильтровать методы класса от их типа возвращаемого значения? (Кажется очень сложно, если я могу проверить равенство возвращаемых типов).

Scala 2,10

UPDATE:

Я не могу зайти в отражательной вселенной Java, поскольку этот тип стерта информация для дженериков как List [Int] (которые становятся List [Object] является Java-земля, где они действительно List [java.lang.Integer]). Мне нужно, чтобы я совпадал с тем, чтобы обратить внимание на общую информацию о параметрах, которую сохраняет юниверс типа scala.

+1

Смотреть другие Q & A о том, как для сравнения типов. http://stackoverflow.com/questions/19724752/how-to-compare-equity-between-scala-reflection-library-type-universe-type-and –

+0

Хм ... искал и пропустил это. Спасибо. – user48956

ответ

3

Используйте =:= для сравнения.

scala> import beans._ 
import beans._ 

scala> :pa 
// Entering paste mode (ctrl-D to finish) 

class VarAndValue { 
    @BeanProperty 
    val value = "";  
} 

// Exiting paste mode, now interpreting. 

defined class VarAndValue 

scala> import reflect.runtime._, universe._ 
import reflect.runtime._ 
import universe._ 

scala> val str = typeOf[String] 
str: reflect.runtime.universe.Type = String 

scala> val ms = typeOf[VarAndValue].declarations filter (m => m.isMethod && m.name.decoded == "getValue") 
warning: there were two deprecation warnings; re-run with -deprecation for details 
ms: Iterable[reflect.runtime.universe.Symbol] = SynchronizedOps(method getValue) 

scala> val mm = ms.toList 
mm: List[reflect.runtime.universe.Symbol] = List(method getValue) 

scala> val m = mm.head.asInstanceOf[MethodSymbol] 
m: reflect.runtime.universe.MethodSymbol = method getValue 

scala> val t = m.returnType 
t: reflect.runtime.universe.Type = java.lang.String 

scala> println(t) 
java.lang.String 

scala> println(str) 
String 

scala> str == t 
res2: Boolean = false 

scala> str match { case `t` => } 
scala.MatchError: String (of class scala.reflect.internal.Types$AliasNoArgsTypeRef) 
    ... 33 elided 

scala> str =:= t 
res4: Boolean = true 

scala> str match { case TypeRef(a,b,c) => (a,b,c) } 
res5: (reflect.runtime.universe.Type, reflect.runtime.universe.Symbol, List[reflect.runtime.universe.Type]) = (scala.Predef.type,type String,List()) 

scala> t match { case TypeRef(a,b,c) => (a,b,c) } 
res6: (reflect.runtime.universe.Type, reflect.runtime.universe.Symbol, List[reflect.runtime.universe.Type]) = (java.lang.type,class String,List()) 

В зависимости от того, что вы собираетесь, считают, что соответствующие типы могут иметь различные представления:

scala> typeOf[List[Int]] 
res11: reflect.runtime.universe.Type = scala.List[Int] 

scala> type X = List[Int] 
defined type alias X 

scala> typeOf[X].dealias 
res12: reflect.runtime.universe.Type = List[scala.Int] 

scala> res11 =:= res12 
res13: Boolean = true 

scala> res11 == res12 
res14: Boolean = false 

scala> typeOf[X] <:< res11 
res15: Boolean = true 

scala> typeOf[X] =:= res11 
res16: Boolean = true 
+0

Означает ли это, что тип не должен использоваться в качестве ключа для карты? – user48956

+1

Это зависит от того, что вы делаете, но не ожидайте, что аналогичные типы с aliased будут сравниваться. Возможно, это то, что вы хотите. Обычно вас интересует соответствие. –

0

Оказывается, это способ для сравнения типов ...

type1 match { 
    case type2 => true 
    case _ => false 
} 

, который дает другой ответ, чем type1 == типа.

Скала - странный зверь.

+1

Нет, ваш 'type2' - это переменная, которая соответствует любому, так же как' type2 @ _'. Нижний регистр означает var в шаблоне. Это небольшая бородавка конвенции. Используйте backticks, чтобы победить его. –

Смежные вопросы