说我们有一个Composite
类
class Composite(val one: Int, val two: Int)
还有一个Host
课程
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
类的直接属性来暴露吗?所以,我想写这样的东西:
fun hostTest() {
val comp = Composite(2, 3)
val hst = Host(comp)
println(hst.one)
println(hst.one)
}
当然,可以在Host
中创建代理属性,但我希望Kotlin作为一种实用语言直接支持这一点。
Kotlin的解决方案是delegation。
您可以通过多种方式实现这一目标,这取决于您的需求,您应该选择哪一种。首先,你需要一个interface
为你的Composite
:
interface Composite {
val one: Int
val two: Int
}
和默认实现:
class DefaultComposite(override val one: Int,
override val two: Int) : Composite
然后你可以使用by
关键字委托Composite
的Host
实例:
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
。
它不是直接可能的,但你可以通过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
,或者你可以使用Composite
初始化时间在Host
子句中可用的任何其他Composite by ...
实例,甚至可以在原地构建一些Composite
。