I'm reflectively invoking a method whose argument might or might not be an instance of a value class. As the purpose of value classes is to avoid boxing of underlying value, if the parameter type is value class then the method in question will in fact expect unboxed value. To handle this case I'm trying to unwrap the underlying value from value class. I first need to determine if the argument is of a value class, and here I hit the first stumbling block:
def isObjectOfValueClass(arg: Any) =
classOf[AnyVal].isAssignableFrom(arg.getClass)
This doesn't work as expected, as the method returns true
for:
case class NonValueClass(underlying: Int)
How can isObjectOfValueClass
be implemented? Or is there a simpler way to reflectively invoke a method that might take object of a value class as an argument?
First, note that your isObjectOfValueClass
will get a boxed version of your value class instances.
Second, it cannot work like you want. It's because classOf[AnyVal] == classOf[AnyRef] == <java.lang.Object>
.
There's no runtime way to distinguish between a boxed value class and a reference class (Any
doesn't have .instanceOf[T]
, AnyVal
cannot be used in pattern matching or as parameter of .instanceOf[T]
, and what's most important, compiled value classes do not extend or implement AnyVal
).
If you want it decided on compile time, then try:
case class IsAnyVal[-T](val value: Boolean) extends AnyVal
implicit def _noClueHowToNameThisImplicit_1 = IsAnyVal[AnyVal](true)
implicit def _noClueHowToNameThisImplicit_2 = IsAnyVal[AnyRef](false)
def isAnyVal[T](arg: T)(implicit ev: IsAnyVal[T]) = ev.value
scala> isAnyVal(1)
res4: Boolean = true
scala> isAnyVal("")
res5: Boolean = false
I'm not sure how you want to extract the sole field of the detected boxed value class instances without more accidental boxing. Besides, Hotspot is pretty good at optimizing small short-lived objects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With