1

ネストされたリストと Scala リフレクションに問題があります。

type のケース クラス フィールドをイントロスペクトするにはどうすればよいList[List[something]]ですか?

ここにいくつかのコードがあります。それは取り除かれています-実際には、反映されたクラスに関する静的データを構築します。興味深い部分はinspectField.

import reflect.runtime.currentMirror
import reflect.runtime.universe._

case class Pet(val name: String, val legs: Int)
case class ListList2(val name: String, val stuff: List[List[Pet]])

object Boom extends App {
    // Introspect class and find all its members (constructor fields)
    val symbol = currentMirror.classSymbol(Class.forName("com.br.ListList2"))
    val constructor = symbol.toType.members.collectFirst {
        case method: MethodSymbol if method.isPrimaryConstructor && method.isPublic && !method.paramss.isEmpty && !method.paramss.head.isEmpty => method
    }.getOrElse( throw new IllegalArgumentException("Case class must have at least 1 public constructor having more than 1 parameters."))

    // Loop through each field
    constructor.paramss.head.map( c => inspectField(c) )

    private def inspectField[T]( sym:Symbol ) : String = {      
        val cname = sym.name.toString
        println("Field: "+cname)
        val cType = sym.typeSignature
        if( cType.typeSymbol.fullName.toString == "scala.collection.immutable.List" ) {
            println("C: "+cType)
            val subtype = cType.asInstanceOf[TypeRef].args(0)  // Goes boom here on first recursive call
            println("Sub:"+subtype)
            inspectField(subtype.typeSymbol)
        }
        "Hi"
    }
}

私のケース クラスは type のフィールドを指定しますList[List[Animal]]inspectFieldコードが再帰的に呼び出されることを期待しています。初めてで問題なし。それは印刷します:

Field: name
Field: stuff
C: scala.List[scala.List[com.br.Pet]]
Sub:scala.List[com.br.Pet]

これまでのところ、それは私が期待していることです。今度は再帰呼び出しで、最初の呼び出しのinspectFieldを渡します。私は次のような出力を期待していました:subtype(List[Pet])

Field: stuff
C: scala.List[com.br.Pet]
Sub:com.br.Pet

代わりに、これは指摘されたエラーでブームになります:

Exception in thread "main" java.lang.ClassCastException: scala.reflect.internal.Types$PolyType cannot be cast to scala.reflect.api.Types$TypeRefApi
4

1 に答える 1