简体   繁体   English

如何将方法的返回类型与 Scala 本机或 TypeTag 进行比较?

[英]How to compare the return type of a method to a Scala native or TypeTag?

So, I'm using the Scala reflections library, and I'm trying to check if a method conforms to a given type.因此,我正在使用 Scala 反射库,并且我正在尝试检查方法是否符合给定类型。 To simplify, I'm trying to check only its output.为了简化,我试图只检查它的 output。

What I have now is:我现在拥有的是:

val returnType = methodSymbol.returnType
// returnType: reflect.runtime.universe.Type = java.lang.String

So, I can read it is a String, but it has this terrible type reflect.runtime.universe.Type .所以,我可以读到它是一个字符串,但它有这种可怕的类型reflect.runtime.universe.Type How on Earth can I compare check if this return type is a simple String?我到底如何比较检查这个返回类型是否是一个简单的字符串? I even tried using TypeTags, which are simple enough, but to convert a Type to a TypeTag is such a monumental effort that I fail to believe such a simple task cannot be achieved with more simply.我什至尝试使用很简单的 TypeTag,但是将Type转换为TypeTag是一项巨大的努力,我不相信这样简单的任务无法用更简单的方式完成。

So, how can I compare this to a String and simply get a boolean back?那么,我怎样才能将其与字符串进行比较并简单地返回 boolean 呢? I thought of simply calling a toString() and trying to parse that back to a normal type, but that would be really disgusting to do on the code, IMO.我想简单地调用一个toString()并尝试将其解析回正常类型,但这在代码上真的很恶心,IMO。 Also, I cannot simply specify the method name, because I'm working on a list of methods, and more will come later.另外,我不能简单地指定方法名称,因为我正在处理一个方法列表,以后还会有更多。

I've seen some questions, and even this (in my opinion, absurdly complex) answer on how to convert a Type to a TypeTag, but, again, I'm baffled by the level of complexity for such a trivial task.我已经看到了一些问题,甚至这个(在我看来,非常复杂)关于如何将 Type 转换为 TypeTag 的答案,但是,我再次对如此微不足道的任务的复杂程度感到困惑。 I'm already thinking of pulling my scarce hair out.我已经在考虑拔掉我稀少的头发了。 Help appreciated.帮助表示赞赏。

EDIT: I've managed to make the comparison for the String itself, but not for a method returning the String.编辑:我已经设法对字符串本身进行了比较,但没有对返回字符串的方法进行比较。

To compare the String return type, I'm doing:为了比较 String 返回类型,我正在做:

val returnType = methodSymbol.returnType
returnType =:= typeTag[String].tpe

When I try to check it with inheritance and a method, though, using <:< , it won't work.但是,当我尝试使用 inheritance 和一种方法检查它时,使用<:< ,它不起作用。 To clarify, B extends Trait A, the type signature is () => B , but I cannot match when coding澄清一下, B 扩展了 Trait A,类型签名是() => B ,但我在编码时无法匹配

val typeSig = methodSymbol.typeSig
typeSig <:< typeTag[() => A].tpe

If you want to work with types as String s you should parse them如果您想将类型作为String使用,您应该解析它们

import scala.reflect.runtime.universe
import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox

val tb = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()
val str = "java.lang.String"
val tpe: Type = (tb.typecheck(tb.parse(s"type T = $str"), mode = tb.TYPEmode) match {
  case q"type T = $typ" => typ
}).tpe // String
tpe =:= typeOf[String] //true

(I would like to do just tb.typecheck(tb.parse(str/*, mode =???*/), mode = tb.TYPEmode).tpe but can't find how to call TypeParser instead of TermParser with runtime reflection, this corresponds to difference between tq"..." and q"..." , otherwise I get String companion instead of String itself. Surely tq"$str" gives wrong type too because it's a macro, it can work only for compile-time literals: tq"java.lang.String" .) (我只想做tb.typecheck(tb.parse(str/*, mode =???*/), mode = tb.TYPEmode).tpe但找不到如何在运行时调用TypeParser而不是TermParser反射,这对应于tq"..."q"..."之间的区别,否则我会得到String伴侣而不是String本身。当然tq"$str"也会给出错误的类型,因为它是一个宏,它只能工作对于编译时文字: tq"java.lang.String" 。)

Maybe not exactly what you're asking for, but you can use java.lang.reflect in Scala.也许不完全符合您的要求,但您可以在 Scala 中使用java.lang.reflect

import java.lang.reflect.Method

class C {
  def doSomething(): String = {
    return "hello"
  }
  def doSomethingElse(): String = {
    return "bye"
  }
  def doNothing(): Int = {
    return 190
  }
}

val doSomethingMethod: Method = classOf[C].getMethods()(2)
val doNothingMethod: Method = classOf[C].getMethods()(1)
val doSomethingElseMethod: Method = classOf[C].getMethods()(0)

// false
doSomethingMethod.getReturnType.equals(doNothingMethod.getReturnType)

// true
doSomethingMethod.getReturnType.equals(doSomethingMethod.getReturnType)

// you can compare the simple name, too, if that's easier
println(s"'${doSomethingMethod.getReturnType.getSimpleName}'")
// 'String'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM