Kotlin:将复合 class 属性公开为 public 主机 class 属性
Kotlin: Expose composite class properties as public host class properties
假设我们有一个 Composite
class
class Composite(val one: Int, val two: Int)
和一个Host
class
class Host(val comp: Composite)
现在我们可以打印 Composite
对象的属性
fun hostTest() {
val comp = Composite(2, 3)
val hst = Host(comp)
println(hst.comp.one)
println(hst.comp.one)
}
在 Kotlin 中是否可以将 Composite
属性公开为 Host
class 的直接属性?
所以,我想写这样的东西:
fun hostTest() {
val comp = Composite(2, 3)
val hst = Host(comp)
println(hst.one)
println(hst.one)
}
当然,可以在 Host
中创建代理属性,但我希望 Kotlin 作为一种实用语言能够直接支持这一点。
这不是直接可能的,但是你可以通过implementation by delegation来模拟它,这需要你将Composite
的属性移动到一个接口:
interface Composite {
val one: Int
val two: Int
}
class CompositeImpl(
override val one: Int,
override val two: Int
) : Composite
class Host(val comp: Composite) : Composite by comp
如果需要,您可以制作 comp
属性 private
,或者您可以使用 [=15= 中提供的任何其他 Composite
实例]在Composite by ...
子句中的初始化时间,甚至就地构造一些Composite
。
Kotlin 对此的解决方案是 delegation。
您可以通过多种方式实现,具体选择哪一种取决于您的需要。首先,您的 Composite
:
需要一个 interface
interface Composite {
val one: Int
val two: Int
}
和默认实现:
class DefaultComposite(override val one: Int,
override val two: Int) : Composite
然后您可以使用 by
关键字从 Host
:
委托给 Composite
的实例
class Host(val composite: Composite) : Composite by composite
如果您对 composite
有合理的默认值:
class CompositeWithDefaults(override val one: Int = 1,
override val two: Int = 2) : Composite
那么你甚至不必将 Composite
作为构造函数参数传递:
class Host() : Composite by CompositeWithDefaults()
或者您可以将其字段传递给 Host
:
class Host(one: Int, two: Int) : Composite by DefaultComposite(one, two)
或者为其设置默认值:
class Host(composite: Composite = CompositeWithDefaults()) : Composite by composite
注意:你不应该委托给可变的 属性,因为使用 by
时生成的字节码将为你的委托使用一个内部字段并且替换原来的对象不会有任何效果。我已经写过这个 here.
如果 composite
是 var
:
,那么生成的 Java 代码就是这样的
public final class Host implements Composite {
@NotNull
private Composite composite;
// $FF: synthetic field
private final Composite $$delegate_0;
@NotNull
public final Composite getComposite() {
return this.composite;
}
public final void setComposite(@NotNull Composite var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.composite = var1;
}
public Host(@NotNull Composite composite) {
Intrinsics.checkParameterIsNotNull(composite, "composite");
super();
this.$$delegate_0 = composite;
this.composite = composite;
}
public int getOne() {
return this.$$delegate_0.getOne();
}
public int getTwo() {
return this.$$delegate_0.getTwo();
}
}
请注意 setter 不会设置 $$delegate_0
,而是 composite
。
假设我们有一个 Composite
class
class Composite(val one: Int, val two: Int)
和一个Host
class
class Host(val comp: Composite)
现在我们可以打印 Composite
对象的属性
fun hostTest() {
val comp = Composite(2, 3)
val hst = Host(comp)
println(hst.comp.one)
println(hst.comp.one)
}
在 Kotlin 中是否可以将 Composite
属性公开为 Host
class 的直接属性?
所以,我想写这样的东西:
fun hostTest() {
val comp = Composite(2, 3)
val hst = Host(comp)
println(hst.one)
println(hst.one)
}
当然,可以在 Host
中创建代理属性,但我希望 Kotlin 作为一种实用语言能够直接支持这一点。
这不是直接可能的,但是你可以通过implementation by delegation来模拟它,这需要你将Composite
的属性移动到一个接口:
interface Composite {
val one: Int
val two: Int
}
class CompositeImpl(
override val one: Int,
override val two: Int
) : Composite
class Host(val comp: Composite) : Composite by comp
如果需要,您可以制作 comp
属性 private
,或者您可以使用 [=15= 中提供的任何其他 Composite
实例]在Composite by ...
子句中的初始化时间,甚至就地构造一些Composite
。
Kotlin 对此的解决方案是 delegation。
您可以通过多种方式实现,具体选择哪一种取决于您的需要。首先,您的 Composite
:
interface
interface Composite {
val one: Int
val two: Int
}
和默认实现:
class DefaultComposite(override val one: Int,
override val two: Int) : Composite
然后您可以使用 by
关键字从 Host
:
Composite
的实例
class Host(val composite: Composite) : Composite by composite
如果您对 composite
有合理的默认值:
class CompositeWithDefaults(override val one: Int = 1,
override val two: Int = 2) : Composite
那么你甚至不必将 Composite
作为构造函数参数传递:
class Host() : Composite by CompositeWithDefaults()
或者您可以将其字段传递给 Host
:
class Host(one: Int, two: Int) : Composite by DefaultComposite(one, two)
或者为其设置默认值:
class Host(composite: Composite = CompositeWithDefaults()) : Composite by composite
注意:你不应该委托给可变的 属性,因为使用 by
时生成的字节码将为你的委托使用一个内部字段并且替换原来的对象不会有任何效果。我已经写过这个 here.
如果 composite
是 var
:
public final class Host implements Composite {
@NotNull
private Composite composite;
// $FF: synthetic field
private final Composite $$delegate_0;
@NotNull
public final Composite getComposite() {
return this.composite;
}
public final void setComposite(@NotNull Composite var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.composite = var1;
}
public Host(@NotNull Composite composite) {
Intrinsics.checkParameterIsNotNull(composite, "composite");
super();
this.$$delegate_0 = composite;
this.composite = composite;
}
public int getOne() {
return this.$$delegate_0.getOne();
}
public int getTwo() {
return this.$$delegate_0.getTwo();
}
}
请注意 setter 不会设置 $$delegate_0
,而是 composite
。