Kotlin:将复合类属性公开为公共主机类属性

Kotlin:将复合类属性公开为公共主机类属性,kotlin,properties,composition,class-design,Kotlin,Properties,Composition,Class Design,假设我们有一个Composite类 class Composite(val one: Int, val two: Int) class Host(val comp: Composite) 和一个主机类 class Composite(val one: Int, val two: Int) class Host(val comp: Composite) 现在我们可以打印复合对象的属性了 fun hostTest() { val comp = Composite(2, 3)

假设我们有一个
Composite

class Composite(val one: Int, val two: Int)
class Host(val comp: Composite)
和一个
主机

class Composite(val one: Int, val two: Int)
class Host(val comp: Composite)
现在我们可以打印
复合对象的属性了

fun hostTest() {
    val comp = Composite(2, 3)
    val hst = Host(comp)

    println(hst.comp.one)
    println(hst.comp.one)
}
在Kotlin中,是否可以将
复合
属性公开为
主机
类的直接属性? 所以,我想写这样的东西:

fun hostTest() {
    val comp = Composite(2, 3)
    val hst = Host(comp)

    println(hst.one)
    println(hst.one)
}

当然,可以在
主机中创建代理属性,但我希望Kotlin作为一种实用语言能够直接支持这一点。

这不可能直接实现,但您可以通过来模拟它,这要求您将
复合
的属性移动到一个接口:

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
Composite by…
子句中主机初始化时可用的任何其他
Composite
实例,甚至在适当的位置构建一些复合材料。

Kotlin的解决方案是

你可以用多种方式来做,这取决于你的需要,你应该选择哪一种。首先,您需要为您的
组合
提供一个
界面

interface Composite {
    val one: Int
    val two: Int
}
class CompositeWithDefaults(override val one: Int = 1,
                            override val two: Int = 2) : Composite
和默认实现:

class DefaultComposite(override val one: Int,
                       override val two: Int) : Composite
然后,您可以使用
by
关键字从
Host
委托给
Composite
的实例:

class Host(val composite: Composite) : Composite by composite
class Host(one: Int, two: Int) : Composite by DefaultComposite(one, two)
如果您有合理的
组合的默认值

interface Composite {
    val one: Int
    val two: Int
}
class CompositeWithDefaults(override val one: Int = 1,
                            override val two: Int = 2) : Composite
然后,您甚至不必将
复合
作为构造函数参数传递:

class Host() : Composite by CompositeWithDefaults()
或者,您可以将其字段传递到
主机

class Host(val composite: Composite) : Composite by composite
class Host(one: Int, two: Int) : Composite by DefaultComposite(one, two)
或具有默认值:

class Host(composite: Composite = CompositeWithDefaults()) : Composite by composite
但是要小心:您不应该委托给可变的属性,因为使用
by
生成的字节码将为您的委托使用一个内部字段,并且替换原始对象将无效。我已经写过了

如果
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();
   }
}
公共最终类主机实现复合{
@NotNull
私人复合材料;
//$FF:合成场地
私有最终复合$$delegate\u 0;
@NotNull
公共最终复合getComposite(){
返回此.composite;
}
公共最终void setComposite(@NotNull Composite var1){
Intrinsics.checkParametersNotNull(var1,“”);
this.composite=var1;
}
公共主机(@NotNull复合){
本质。检查参数完整(复合,“复合”);
超级();
此$$delegate_0=复合;
这个。复合=复合;
}
公共整数getOne(){
返回此值。$$delegate_0.getOne();
}
公共int getTwo(){
返回此值。$$delegate_0.getTwo();
}
}

请注意,setter并没有设置
$$delegate\u 0
,而是设置
composite

Thx,这正是我所需要的,因为我的composite是一个第三方类,有很多属性需要打包。很抱歉,我告诉你,你的第二个链接已经死了。