0

次の例では、id が AnyVal であることがテストで出力されるように、オブジェクトが値クラス型であるかどうかを確認するにはどうすればよいですか?

class MyId(val underlying: Int) extends AnyVal

class AnyValSuite extends FunSuite {

  class Sample {
    def doIt[T](t: T)(implicit tag: TypeTag[T]): Unit = {
      if(???) println(s"$t is an AnyVal")     
    }
  }

  test("Getting info if a type is a value class") {
    new Sample().doIt(new MyId(1))
  }
}

@セニア:答えてくれてありがとう。完璧に動作します。Value クラスがラップしているプリミティブ型を見つけることも可能ですか?

例を拡張しました:

class MyId(val underlying: Int) extends AnyVal
class NonAnyValId(val underlying: Int)

class AnyValSuite extends FunSuite {

  class Sample {
    def doIt[T](t: T)(implicit tag: TypeTag[T]): Unit = {
      if(implicitly[TypeTag[T]].tpe <:< typeOf[AnyVal]) println(s"$t is an AnyVal")
      else println(s"$t is not an AnyVal")
    }
  }

  test("Getting info if a type is a value class") {
    new Sample().doIt(new MyId(1))
    new Sample().doIt(new NonAnyValId(1))
    new Sample().doIt(1)
  }
}

戻り値:

MyId@1 is an AnyVal
NonAnyValId@38de28d is not an AnyVal
1 is an AnyVal

編集 2: ラップされた型チェックを使用:

import org.scalatest.FunSuite
import scala.reflect.runtime.universe._

class MyId(val underlying: Int) extends AnyVal
class NonAnyValId(val underlying: Int)

class AnyValSuite extends FunSuite {

  class Sample {
    def doIt[T](t: T)(implicit tag: TypeTag[T]): Unit = {
      val tpe= implicitly[TypeTag[T]].tpe
      if(tpe <:< typeOf[AnyVal])  {
        println(s"$t is an AnyVal")
        val fields = tpe.members.filter(! _.isMethod)

        fields.size  match {
          case 0 => println("has no fields, so it's a primitive like Int")
          case 1 => {
            println("has a sole field, so it's a value class")
            val soleValueClassField = fields.head.typeSignature
            println("of type: " + soleValueClassField)
            if(typeOf[Int] == soleValueClassField) println("It wraps a primitive Int")
          }
          case 2 => throw new Exception("should never get here")
        }
      }
      else println(s"$t is not an AnyVal")
    }
  }

  test("Getting info if a type is a value class") {
    new Sample().doIt(new MyId(1))
    println
    new Sample().doIt(new NonAnyValId(1))
    println
    new Sample().doIt(1)
  }
}

戻り値:

MyId@1 is an AnyVal
has a sole field, so it's a value class
of type: Int
It wraps a primitive Int

NonAnyValId@3d0d4f51 is not an AnyVal

1 is an AnyVal
has no fields, so it's a primitive like Int

もっと簡単な解決策があるかどうか疑問に思っていますか?

4

1 に答える 1

5

Tのサブタイプであるかどうかを確認できますAnyVal

import scala.reflect.runtime.universe.{TypeTag, typeOf}

def doIt[T: TypeTag](t: T): Unit = {
  if(implicitly[TypeTag[T]].tpe <:< typeOf[AnyVal]) println(s"$t is an AnyVal")     
}

doIt(new MyId(1))
// $line18.$read$$iw$$iw$$iw$$iw$MyId@1 is an AnyVal
于 2013-11-14T17:40:48.593 に答える