Как я могу получить значение по умолчанию параметра конструктора для не-case класса? - PullRequest
0 голосов
/ 27 февраля 2019
class Person(name: String, age: Int, numThings: Option[Int] = Some(15))

Я могу использовать отражение Scala, чтобы получить значения по умолчанию для класса дел, например:

   val companionType: Type = classSymbol.companion.typeSignature
   val companionObject = currentMirror.reflectModule(classSymbol.companion.asModule).instance
   val companionMirror = currentMirror.reflect(companionObject)
   val defaultValueAccessorMirror =
   if (member.typeSignature.typeSymbol.isClass) {
     val defaultValueAccessor = companionType.member(TermName("apply$default$" + (index + 1)))
     if (defaultValueAccessor.isMethod) {
       Some(companionMirror.reflectMethod(defaultValueAccessor.asMethod))
     } else {
       None
     }
   } else {
     None
   }

Получает метод в сгенерированном объекте-компаньоне, который при вызове выкашливает значение по умолчанию.К сожалению, не-case класс, кажется, не имеет этой возможности.

Как я могу получить значение по умолчанию для Person.numThings в приведенном выше примере, используя отражение Scala или Java?

1 Ответ

0 голосов
/ 28 февраля 2019

Я думаю, что гораздо проще получить эти значения по умолчанию с помощью отражения Java, а не слишком сложного отражения Scala ...

При компиляции в файл .class значения параметров по умолчанию переводятсяв статические методы с конкретными суффиксами в именах.Эти значения можно получить, вызвав соответствующий метод для ссылки на класс.

Так, например, у нас есть классы case и не-case:

class Person(name: String, age: Int, numThings: Option[Int] = Some(15))

case class Item(id: Long, other: String = "unknown")

Firstнам нужно определить порядковые индексы параметров для получения значений по умолчанию.Я не знаю ваш вариант использования, поэтому давайте предположим, что вы знаете или рассчитали их.Они будут 3 для Person и 2 для Item.Да, они , а не 0.

И этот очень короткий метод возвращает значения:

private def extractDefaultConstructorParamValue(clazz: Class[_],
                                                iParam: Int): Any = {
  val methodName = "$lessinit$greater$default$" + iParam
  clazz.getMethod(methodName).invoke(clazz)
}

Вызов их с помощью

val defParamNonCase = extractDefaultConstructorParamValue(classOf[Person], 3)
val defParamCase = extractDefaultConstructorParamValue(classOf[Item], 2)

println(defParamNonCase)
println(defParamCase)

выходы

Some(15)
unknown
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...