KotlinPoet: добавить функцию в существующий класс - PullRequest
0 голосов
/ 16 декабря 2018

Я хочу создать процессор аннотаций, который генерирует общедоступную функцию получения «не изменяемого класса» из частного поля «изменяемого класса» (например, возвращая LiveData версию поля MutableLiveData).

То, что я хочу написать:

class MyClass {  
    @WithGetNonMutable  
    private val popup: MutableLiveData<PopupTO?> = MutableLiveData()  
}

То, что я хочу сгенерировать

class MyClass {  
    private val popup: MutableLiveData<PopupTO?> = MutableLiveData()  
    fun getPopup(): LiveData<PopupTO?> = popup  
}

Генерация функции с правильным типом возврата не является проблемой:

val liveDataType = ClassName("android.arch.lifecycle", "LiveData")
val returnType = liveDataType.parameterizedBy(genericDataType)

val function = FunSpec.builder("get${element.simpleName}")
                .addModifiers(KModifier.PUBLIC)
                .addStatement("return ${element.simpleName}")
                .returns(returnType)
                .build()

Проблема в том, что переменная (popup) является закрытой - поэтому для доступа к ней моя сгенерированная функция также должна быть частью этого класса (она не может быть простой функцией расширения в новом файле),Все примеры KotlinPoet пишут в новые файлы - но нет возможности получить доступ к закрытому полю (или есть?), Поэтому мне нужно написать функцию в фактическом файле класса?Как мне этого добиться?

1 Ответ

0 голосов
/ 11 января 2019

Процессоры аннотаций не могут изменять существующий код, они могут только генерировать новый код.


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

  1. Сохраните MyClass (с модификатором private, измененным на internal):
class MyClass {  
    @WithGetNonMutable  
    internal val popup: MutableLiveData<PopupTO?> = MutableLiveData()  
}
Создайте новый файл (в том же пакете) со следующим содержимым:
fun MyClass.getPopup(): LiveData<PopupTO?> = this.popup  

Если вы не можете полностью изменить MyClass (вы не можетеизменить private на internal), вы можете (это не так уж и элегантно, но вы можете сделать это):

В сгенерированной функции расширения используйте Reflection для доступа к закрытому полю.

...