【问题标题】:KotlinPoet: Add function to existing classKotlinPoet:向现有类添加函数
【发布时间】:2019-05-17 06:48:16
【问题描述】:

我想构建一个注释处理器,它生成私有“可变类”字段的公共“非可变类”getter 函数(例如,返回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 示例都写入新文件 - 但无法访问私有字段(或者是否存在?)所以我需要在实际的类文件中编写函数?我怎样才能做到这一点?

【问题讨论】:

  • KotlinPoet(和一般的注释处理)是关于生成新代码而不是更改现有代码。所以你不能真正修改那个类。
  • 您可能会考虑编写一个编译器插件,将 getter 直接添加到字节码中。总之,KotlinPoet 只是生成代码的助手,它并不知道也不关心注解处理或编译的机制。

标签: kotlin code-generation kotlinpoet


【解决方案1】:

注解处理器不能修改现有代码,它们只能生成新代码。


也就是说,您可以修改您的方法并生成扩展函数而不是成员函数。

  1. 保留您的MyClass(将private 修饰符更改为internal):
class MyClass {  
    @WithGetNonMutable  
    internal val popup: MutableLiveData<PopupTO?> = MutableLiveData()  
}
  1. 生成一个新文件(在同一个包中),包含以下内容:
fun MyClass.getPopup(): LiveData<PopupTO?> = this.popup  

如果你完全不能修改MyClass(你不能把private改成internal),你可以(没那么优雅,但你可以做到):

在生成的扩展函数中使用Reflection 访问私有字段。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-14
    • 1970-01-01
    • 1970-01-01
    • 2012-12-13
    • 1970-01-01
    • 2017-02-11
    • 1970-01-01
    • 2016-02-10
    相关资源
    最近更新 更多