假设我们有一个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作为一种实用语言能够对此提供直接支持。
答案 0 :(得分:1)
在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();
}
}
请注意,设置器没有设置$$delegate_0
,而是设置了composite
。
答案 1 :(得分:0)
这不可能直接实现,但是您可以通过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
。