Kotlin: комбинированные операторы case, запрещение доступа к переменной-члену - PullRequest
0 голосов
/ 11 сентября 2018

В моем утверждении when у нас есть 3 случая, которые выполняют аналогичную вещь.

private fun bindValue(target: Activity) {
    val declaredFields = target::class.java.declaredFields

    for (field in declaredFields) {
        for (annotation in field.annotations) {

            when(annotation) {
                is ReflectSource -> {
                    field.isAccessible = true
                    field.set(target, annotation.value)
                }
                is ReflectBinary -> {
                    field.isAccessible = true
                    field.set(target, annotation.value)
                }
                is ReflectRuntime -> {
                    field.isAccessible = true
                    field.set(target, annotation.value)
                }
            }
        }
    }
}

Поэтому я подумал о слиянии их, как показано ниже

private fun bindValue(target: Activity) {
    val declaredFields = target::class.java.declaredFields

    for (field in declaredFields) {
        for (annotation in field.annotations) {

            when(annotation) {
                is ReflectSource, is ReflectBinary, is ReflectRuntime -> {
                    field.isAccessible = true
                    field.set(target, annotation.value)
                }
            }
        }
    }
}

Однако,он ошибочно заявляет, что value из annotation недоступен.Зачем?Не могу ли я объединить эти 3 оператора case?

Обновление Мои три класса, как показано ниже

@Retention(AnnotationRetention.SOURCE)
@Target(AnnotationTarget.FIELD)
annotation class ReflectSource(val value: Int)

@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.FIELD)
annotation class ReflectBinary(val value: Int)

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FIELD)
annotation class ReflectRuntime(val value: Int)

1 Ответ

0 голосов
/ 11 сентября 2018

Не могу ли я объединить эти 3 случая?

Нет, ты не можешь. Помните, как это работает в

is ReflectSource -> {
    field.isAccessible = true
    field.set(target, annotation.value)
}

case: annotation.value скрывает приведение, вставленное компилятором, это действительно (annotation as ReflectSource).value.

К какому классу должен быть преобразован компилятор при использовании is ReflectSource, is ReflectBinary, is ReflectRuntime?

В принципе, компилятор мог бы справиться с этим, но это усложнило бы описание языка и реализацию для довольно редкого случая.

Один из вариантов уменьшения дублирования:

val value = when(annotation) {
    is ReflectSource -> annotation.value
    is ReflectBinary -> annotation.value
    is ReflectRuntime -> annotation.value
    else -> null
}
value?.let {
    field.isAccessible = true
    field.set(target, it)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...