9

Generic スーパークラスがあると仮定します。

class GenericExample[T](
                         a: String,
                         b: T
                       ) {

  def fn(i: T): T = b
}

および具象サブクラス:

case class Example(
                    a: String,
                    b: Int
                  ) extends GenericExample[Int](a, b)

関数 "fn" の型パラメーターを scala リフレクションによって取得したいので、そのメンバーを選択してフィルター処理します。

import ScalaReflection.universe._

val baseType = typeTag[Example]

val member = baseType
  .tpe
  .member(methodName: TermName)
  .asTerm
  .alternatives
  .map(_.asMethod)
  .head

    val paramss = member.paramss
    val actualTypess: List[List[Type]] = paramss.map {
      params =>
        params.map {
          param =>
            param.typeSignature
        }
    }

私はscalaが正しい結果を与えることを期待していましたList(List(Int)).List(List(T))

ドキュメントをざっと見てみると、typeSignature が原因であることがわかりました。

 *  This method always returns signatures in the most generic way possible, even if the underlying symbol is obtained from an
 *  instantiation of a generic type.

そして、別の方法を使用することをお勧めします:

def typeSignatureIn(site: Type): Type

ただし、クラス Example はもはやジェネリックではないため、typeTag[Example] からサイトを取得する方法はありません。それとも、それを行う方法がなく、Java リフレクションに戻す必要がありますか?

どうもありがとうございました。

更新:いくつかの簡単なテストの後、MethodSymbol.returnTypeでさえ意図したとおりに機能しないことがわかりました。次のコード:

member.returnType

次のコードは結果を変更しないため、asSeenFromT修正することはできません。

member.returnType.asSeenFrom(baseType.tpe, baseType.tpe.typeSymbol.asClass)
4

2 に答える 2

1

私は自分の解決策を投稿しています: Scala の設計のため、代替手段はないと思います:

Scala リフレクションと Java リフレクションのメソッドの主な違いはカリー化です。Scala メソッドは多くの括弧のペアで構成され、最初に引数を指定してメソッドを呼び出すと、より多くの括弧のペアを取ることができる無名クラスを構築するだけです。または、ブラケットが残っていない場合、メソッドの結果を生成するために解決できる NullaryMethod クラス (別名、名前による呼び出し) を構築します。そのため、scala メソッドのタイプは、メソッドがすでに Method & NullaryMethod Signatures に分割されている場合にのみ、このレベルで解決されます。

その結果、結果の型は再帰を使用してのみ取得できることが明らかになります。

  private def methodSignatureToParameter_ReturnTypes(tpe: Type): (List[List[Type]], Type) = {
    tpe match {
      case n: NullaryMethodType =>
        Nil -> n.resultType
      case m: MethodType =>
        val paramTypes: List[Type] = m.params.map(_.typeSignatureIn(tpe))
        val downstream = methodSignatureToParameter_ReturnTypes(m.resultType)
        downstream.copy(_1 = List(paramTypes) ++ methodSignatureToParameter_ReturnTypes(m.resultType)._1)
      case _ =>
        Nil -> tpe
    }
  }

  def getParameter_ReturnTypes(symbol: MethodSymbol, impl: Type) = {

    val signature = symbol.typeSignatureIn(impl)
    val result = methodSignatureToParameter_ReturnTypes(signature)
    result
  }

implメソッドを所有するクラスはどこにあり、 scala リフレクションによってsymbol取得したものですType.member(s)

于 2016-07-19T18:54:10.807 に答える