从覆盖内使用 class 委托时调用(基本)委托函数

Calling (base) delegated function when using class delegation from within override

重写由 class delegation 实现的接口方法时,是否可以从重写函数中调用通常委托给的 class?类似于使用继承时调用 super 的方式。

来自documentation

interface Base {
    fun print()
}

class BaseImpl(val x: Int) : Base {
    override fun print() { print(x) }
}

class Derived(b: Base) : Base by b

fun main(args: Array<String>) {
    val b = BaseImpl(10)
    Derived(b).print() // prints 10
}

Note that overrides work as you might expect: The compiler will use your override implementations instead of those in the delegate object.

override fun print() { ... }

如何从这个被覆盖的函数中调用 BaseImpl print() 函数?

用例是我想向这个函数添加额外的逻辑,同时重用现有的实现。

您可以直接从 属性 b 调用函数 print(),但为此您需要将简单的构造函数参数 b: Base 更改为将参数保存为 属性private val b: Base

希望对您有所帮助。

由于Base是一个接口,你不能真正调用super(类似于Java)。

相反,您需要将 b 声明为字段并直接使用它:

class Derived(val b: Base) : Base by b {
    override fun print() {
        b.print()
        // ...
    }
}

并且当委托给的 class 作为参数传递(依赖注入)时应该是合适的。

然而,在我更具体的用例中(很抱歉没有说清楚 ),实现是直接在委托定义中定义的。

class Derived(b: Base) : Base by BaseImpl()

在这种情况下,Egor 的回答不起作用,需要更详细的方法。如果您希望隐藏实现以便调用者无法修改它,则可以使用以下实现。例如,在我的特定用例中,我正在创建一个 aggregate root 并希望保护内部不变量。

open class HiddenBaseImpl internal constructor( protected val _b: Base ) : Base by _b

class Derived() : HiddenBaseImpl( BaseImpl() )
{
    override fun print()
    {
        _b.print()

        ... do something extra
    }
}

由于 HiddenBaseImpl 的主要构造函数只能在内部使用,库的调用者无法实例化此 class,因此被迫使用 DerivedDerived 现在可以在内部调用委托给 class 并添加额外的行为,而不允许调用者传递 Base.

的不同实现

您只能在 Kotlin 中使用 super 来访问超类,不能使用接口或其他奇怪的东西(记住 - Kotlin 在 JVM 上是 运行)。但是,如果将派生实例存储在变量中绝对没问题,例如 .

为避免任何人都可以设置或检索变量,您可以使用私有(或受保护,无论适合您的用例)主构造函数并添加第二个 public 构造函数:

interface Base {
    fun print()
}

class BaseImpl() : Base {
    override fun print() { print(x) }
}

class Derived private constructor(private val b : Base) : Base by b {
    constructor() : this(BaseImpl())

    override fun print() = b.print()
}

fun main(args: Array<String>) {
    val d = Derived()
    d.b // does not work, compiler error
    d.print() // prints 10
}

我想我对此有更好的解决方案。 它更优雅,因为不需要额外的 class 并且它与批准的完全相同。

interface Base {
    fun print()
}

class Derived private constructor (private val delegate: Base): Base by delegate {
constructor(): this(BaseImpl())

    override fun print{
      delegate.print()
    }
}