【问题标题】:Why only interfaces can be delegated to in kotlin?为什么在 kotlin 中只能委托接口?
【发布时间】:2018-03-05 09:06:25
【问题描述】:

我很少看到类似的问题,但没有人解释为什么委托仅限于接口?

在实践中,大多数时候我们有一些实际上根本没有接口的东西,它是一个什么都不实现但提供一些功能或实现一个抽象类的类。

是否有任何基本限制迫使其仅限于接口,或者我们可以期望 kotlin 在未来拥有不受限制的委托?

如果我们想使用组合而不是继承来扩展类的功能,这尤其有用。

class A {}
class B(val a: A) : A by a {}

【问题讨论】:

    标签: kotlin delegation


    【解决方案1】:

    当您委托一个接口时,该类仍然实现该接口。所以为了一致性,如果你可以委托一个类,它应该以同样的方式工作。 IE。

    class A(x: Int) {
      fun foo() = x
    }
    
    class B(val a: A) : A by a {}
    

    需要编译成

    class B(val a: A) : A {
      override fun foo() = a.foo()
    }
    

    除非这不起作用:

    1. foo 不是open,不能被覆盖。

    2. 你需要调用A的构造函数。 class B(val a: A) : A(a.x) 也无济于事:x 不是 A 的成员。

    3. equals 和 hashCode 呢:他们被授权了吗?任何一个决定都会导致奇怪的后果。

    【讨论】:

    • 1.所以它不应该试图覆盖它。只有可覆盖的方法(open 或 abstact)应该被自动委派。 2. 所以应该要求B 像往常一样将构造函数参数传递给A。 3. Kotlin 作者已经不得不为接口委托做出这个决定,因为每个接口都隐式扩展Any,因此具有equals、hashCode 和toString。
    • 当然,这是一组可能的答案。但是你不会“使用组合而不是继承来扩展类的功能”;你有一个非常奇怪的组合和继承组合,并且在 A 中打开一个方法而不改变它的行为(例如,因为你发现 C 需要覆盖它)可以改变 B 的行为。
    • 如果A作为构造函数参数B传递给a,你将如何以及为什么调用A的构造函数?
    • 为什么:因为要扩展A,您的主构造函数总是必须调用A 的构造函数。如何:嗯,这正是问题所在。
    猜你喜欢
    • 2020-08-22
    • 2010-10-11
    • 1970-01-01
    • 2021-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-30
    • 2019-09-08
    相关资源
    最近更新 更多