Scala: распознавание объектов классов значений

Я рефлективно вызываю метод, аргумент которого может быть или не быть экземпляром класс значения. Поскольку цель классов значений состоит в том, чтобы избежать упаковки базового значения, если тип параметра является классом значения, то рассматриваемый метод фактически будет ожидать неупакованного значения. Чтобы справиться с этим случаем, я пытаюсь развернуть базовое значение из класса значений. Сначала мне нужно определить, относится ли аргумент к классу значений, и здесь я натыкаюсь на первый камень преткновения:

def isObjectOfValueClass(arg: Any) = 
  classOf[AnyVal].isAssignableFrom(arg.getClass)

Это не работает должным образом, так как метод возвращает true для:

case class NonValueClass(underlying: Int)

Как можно реализовать isObjectOfValueClass? Или есть более простой способ рефлексивно вызвать метод, который может принимать объект класса значения в качестве аргумента?


person narthi    schedule 29.10.2013    source источник
comment
Кстати, класс value может оборачивать не только примитивы, но и объекты.   -  person om-nom-nom    schedule 29.10.2013


Ответы (1)


Во-первых, обратите внимание, что ваш isObjectOfValueClass получит коробочную версию ваших экземпляров классов значений.

Во-вторых, он не может работать так, как вы хотите. Это потому, что classOf[AnyVal] == classOf[AnyRef] == <java.lang.Object>.

Во время выполнения нет способа отличить упакованный класс значений от ссылочного класса (Any не имеет .instanceOf[T], AnyVal не может использоваться при сопоставлении с образцом или в качестве параметра .instanceOf[T], и, что наиболее важно, скомпилированные классы значений не расширяют и не реализуют AnyVal ).

Если вы хотите, чтобы было принято решение о времени компиляции, попробуйте:

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

Я не уверен, как вы хотите извлечь единственное поле обнаруженных экземпляров класса значений в штучной упаковке без дополнительной случайной упаковки. Кроме того, Hotspot неплохо справляется с оптимизацией небольших недолговечных объектов.

person Karol S    schedule 29.10.2013