2

当数据类扩展一个包含非抽象 open val 属性的密封类时,生成的子数据类包含与父类的私有字段重复的私有字段。

sealed class Foo(open val field1: String? = null)

data class Bar(override val field1: String? = null) : Foo(field1)

输出javap -p Foo.class

public abstract class com.example.Foo {
    private final java.lang.String field1;
    public java.lang.String getField1();
    private com.example.Foo(java.lang.String);
    com.example.Foo(java.lang.String, int, kotlin.jvm.internal.DefaultConstructorMarker);
    public com.example.Foo(java.lang.String, kotlin.jvm.internal.DefaultConstructorMarker);
}

并且javap -p Bar.class

public final class com.example.Bar extends com.example.Foo {
    private final java.lang.String field1;
    public java.lang.String getField1();
    public com.example.Bar(java.lang.String);
    public com.example.Bar(java.lang.String, int, kotlin.jvm.internal.DefaultConstructorMarker);
    public com.example.Bar();
    public final java.lang.String component1();
    public final com.example.Bar copy(java.lang.String);
    public static com.example.Bar copy$default(com.example.Bar, java.lang.String, int, java.lang.Object);
    public java.lang.String toString();
    public int hashCode();
    public boolean equals(java.lang.Object);
}

的字节码Bar.class包含自己的私有字段field1;父类中的字段似乎没有被子类重用。

当使用使用反射设置字段的框架时,将设置哪个字段?为什么父类中的字段不被子类重用?有没有办法改变父类中字段的可见性,protected以便子类可以重用它?

4

3 回答 3

0

当使用使用反射设置字段的框架时,将设置哪个字段?

这取决于您使用的类。Foo::class.java.getDeclaredField()Bar::class.java.getDeclaredField()

看:

为什么父类中的字段不被子类重用?

为什么要呢?field1您在两个类中定义了一个字段支持的属性。这两个字段都将存在,但getField1()方法被子类覆盖以返回子类的字段。

有没有办法将父类中字段的可见性更改为受保护,以便子类可以重用它?

lateinit 属性的字段与 getter 具有相同的可见性。但我不确定这就是你想要的。

这个怎么样?

sealed class Foo {
    abstract val field1: String?
}

data class Bar(override val field1: String? = null) : Foo()

请参阅此处的讨论:https ://twitter.com/orangy/status/1033067930248867840

于 2018-08-25T13:52:55.103 回答
0

在那种情况下Bar,确实拥有该领域两次。具有单个字段的两种选择:

sealed class Foo(val field1: String?)
data class Bar(private val hiddenField1: String? = null) : Foo(hiddenField1)

或者

sealed class Foo {
    abstract val field1: String?
}
data class Bar(override val field1: String? = null) : Foo()
于 2018-08-18T16:32:46.733 回答
0

该字段未被重用,因为您声明了一个单独的属性,该属性具有自己的支持字段。如果要重用该字段,请将代码更改为:

sealed class Foo(val field1: String? = null)

data class Bar(field1: String? = null) : Foo(field1)
于 2018-08-17T17:14:40.390 回答