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