0
如何找出某个对象是否为值类类型,以便在下面的示例中,测试会打印出该id是否为AnyVal?Scala TypeTags或Manifest:是否可以确定某个类型是否是Value类?
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))
}
}
@senia:谢谢你的回答。完美的作品。是否有可能找出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)
}
}
回报:
[email protected] is an AnyVal
[email protected] 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)
}
}
回报:
[email protected] is an AnyVal
has a sole field, so it's a value class
of type: Int
It wraps a primitive Int
[email protected] is not an AnyVal
1 is an AnyVal
has no fields, so it's a primitive like Int
只是不知道是否有一些简单的解决方案?
@flavian:你是什么意思?您可以请添加代码示例。 – senia
@senia感谢您的完美!是否有可能获得值类的包装原始类型? – longliveenduro
@longliveenduro:'value class'应该只有一个字段,所以你可以使用scala反射来找到这个字段。 – senia