【问题标题】:Kotlin: function delegationKotlin:函数委托
【发布时间】:2017-11-28 11:02:43
【问题描述】:

我有一个项目在很大程度上依赖于 Kotlin 中的委托和组合。委托属性是轻而易举的事,但从概念上讲,我不完全确定在函数依赖于其他组合属性的情况下如何实现函数的委托。我想做这样的事情:

interface A {
  val a: String
}
class AImpl: A {
  override val a = "a"
}
interface B {
  val b: String
}
class BImpl: B {
  override val b = "b"
}

interface C<T> where T: A, T: B {
  fun c() : String
}

class CImpl<T>(val ab: T) : C<T> where T: A, T: B {
  override fun c() = ab.a + ab.b
}

// works
class ABC : A by AImpl(), B by BImpl()

// does not work
class ABC : A by AImpl(), B by BImpl(), C<ABC> by CImpl(this)

当然,这种类型的事情可以通过以下方式实现:

interface A {
  val a: String
}
class AImpl: A {
  override val a = "a"
}
interface B {
  val b: String
}
class BImpl: B {
  override val b = "b"
}

interface C<T> where T: A, T: B {
  fun c() : String
}

class CImpl<T>(val ab: T) : C<T> where T: A, T: B {
  override fun c() = ab.a + ab.b
}

class AB : A by AImpl(), B by BImpl()

class ABC(ab: AB = AB(), c: C<AB> = CImpl<AB>(ab)) : A by ab, B by ab, C<AB> by c

但这感觉很笨拙,因为它需要传递对象以进行组合,这会使构造函数的大小膨胀——对我来说,在类本身的位置初始化对象会更干净,因为它们在类之外没有用处。委托和/或扩展是否有一种优雅的方法?

【问题讨论】:

  • 好问题。我对此进行了一些测试,发现您可以在上一个示例中删除c 参数,然后写下:class ABC(ab: AB = AB()) : A by ab, B by ab, C&lt;AB&gt; by CImpl&lt;AB&gt;(ab)
  • 感谢您的建议!这绝对是朝着正确方向迈出的一步。让构造函数 100% 无参数仍然很好,因为我在工厂方法中传递了很多构造函数,如果它们都具有相同的签名会更简洁。
  • 这里的委托似乎是一种反模式/滥用。上面的代码尝试委托其所有邻居。它失去了 oop 中的 封装 优点。而且我认为这个功能永远不会在 kotlin 中发布,因为它会导致这样的神级难以使用。
  • 我不同意 - 假设有委托属性 firstNamelastName 然后我们还想委托一个函数 namePrinter 打印格式化版本的 firstName 和 @ 987654329@。 namePrinter 可能属于一个实现类,它封装了各种私有函数,但满足 namePrinter 契约,因此可以用作委托。神级反模式会将一堆类似 namePrinter 的函数堆积到一个类中,但似乎使用委托实际上有助于避免这样的反模式。

标签: kotlin delegation


【解决方案1】:

您可以使 C 扩展 AB 而不是将委托传递给它。例如:

interface C : A, B {
    fun c(): String
}

abstract class CImpl() : C {
    abstract override val a: String
    abstract override val b: String
    override fun c(): String = a + b
}

class ABC : A by AImpl(), B by BImpl(), CImpl()

您也可以使用C 中的默认实现而不使用CImpl

interface C : A, B {
    fun c(): String = a + b
}

class ABC : A by AImpl(), B by BImpl(), C

【讨论】:

  • 这真是个好东西!尤其是第二个选项,因为它对组合更友好。
【解决方案2】:

我认为目前支持的不是很好,但是有一个 issue 跟踪这个和相关的功能请求。 (请参阅 Peter Niederwieser 对此问题的评论。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    • 2018-03-30
    • 2021-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多