Сбой проверки типа для суперкласса memberProperty returnType - PullRequest
0 голосов
/ 01 июля 2018

У меня есть экземпляр объекта, который я проверяю на memberProperties, к которым прикреплена правильная аннотация. Затем я хочу фильтровать по типу возвращаемого значения. Например, если объявление выглядит следующим образом: class AutoValidatedThing : AutoValidatedUserInputComponent {...} и целевой экземпляр содержит @ValidComponent val someProperty: AutoValidatedThing = ..., я бы хотел получить someProperty как AutoValidatedUserInputComponent до конца следующего блока кода:

    val invalidOnes = this::class.memberProperties
        .filter { it.javaField != null && it.javaField!!.isAnnotationPresent(ValidComponent::class.java) }
        .filter { val annotations = it.javaField?.annotations; annotations != null
                && annotations.map { ann -> ann.annotationClass }.contains(ValidComponent::class)
                && it.returnType is AutoValidatedUserInputComponent }
        .map { it.getter.call() as AutoValidatedUserInputComponent }

Но it.returnType is AutoValidatedUserInputComponent ВСЕГДА возвращает false.

AutoValidatedUserInputComponent - простой интерфейс:

interface AutoValidatedUserInputComponent {
    fun blabla() : SomeType
}

1 Ответ

0 голосов
/ 01 июля 2018

Вызов returnType для KProperty не возвращает экземпляр с данным типом, с которым можно выполнить проверку is - он возвращает класс отражения, описывающий тип, в частности KType, что, конечно, не реализует ваш интерфейс. Вместо использования is вы можете вызвать isSubTypeOf и проверить, является ли это подтипом другого данного KType.

Для этого вызова вам нужно получить KType для вашего собственного интерфейса - для этого вы можете использовать createType на его KClass:

val targetType = AutoValidatedUserInputComponent::class.createType(nullable = true)

Часть обнуляемости зависит от вас, и есть также другие дополнительные параметры для createType, если ваш интерфейс может иметь параметры типа, например.

Тогда, как я уже говорил, вы можете использовать isSubTypeOf:

val invalidOnes = this::class.memberProperties
        .filter { it.javaField != null && it.javaField!!.isAnnotationPresent(ValidComponent::class.java) }
        .filter {
            val annotations = it.javaField?.annotations
            annotations != null
                    && annotations.map { ann -> ann.annotationClass }.contains(ValidComponent::class)
                    && it.returnType.isSubtypeOf(targetType)
        }
        .forEach {
            println("Found field with annotation and given supertype: $it")
        }
...