初始化时,翻新会跳过数据类的init {}块

时间:2019-10-06 19:01:50

标签: object kotlin initialization retrofit pojo

我将基于Data的参数在类DClass中设置变量

abstract class Data(p: String) {
    var a1: String
    var a2: String

    init {
        """(\w+)(\d+)""".toRegex().find(p)!!.groupValues.run {
            a1 = "a1 is ${get(1)}"
            a2 = "a2 is ${get(2)}"
        }
    }
}

data class DClass(val p1: String, val p2: String) : Data(p1)

然后,我可以在创建a1之后获得a2DClass的值:

DClass("string1", "string2").run { println("$a1 $a2") }

它应返回“ a1是string a2是1

接下来,我尝试通过适当的JSON响应进行改造,以初始化DClass: @GET("loadDClass") suspend fun dClass(): DClass

并说程序执行a1a2的相同输出,它只是返回:

“ a1是null,a2是null”。

因此,我发现init{}的{​​{1}}块被跳过了,因为改型仅生成Data而未进行初始化

是否可以在不手动进行的情况下初始化抽象类的变量?

1 个答案:

答案 0 :(得分:0)

之所以没有调用init块是因为GsonConverterFactory(我假设您会使用它,因为在这种情况下它很常见)以一种特殊的方式构造了DClass而不调用它构造函数。特别是,使用了一个名为UnsafeAllocator的内部类。该类的JavaDoc指出:

/**
 * Do sneaky things to allocate objects without invoking their constructors.
 * [...]
 */

您可以编写自己的翻新版Converter.Factory,但这将使IMO显得过大。建议您向DClass添加一个简单的成员函数,而不要从Data继承,并从abstract中删除Data关键字。 DClass应该看起来像这样:

data class DClass(val p1: String, val p2: String)
    fun newData(): Data = Data(p1)
}

然后您可以根据响应的Data来构建body()实例:

call.execute().body()?.newData()?.run { println("$a1 $a2") }