从重写中使用类委派时调用(基本)委派函数

Ste*_*ris 1 kotlin kotlin-delegate

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

文档中

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
}
Run Code Online (Sandbox Code Playgroud)

请注意,重写将按您期望的那样工作:编译器将使用重写实现,而不是委托对象中的实现。

override fun print() { ... }
Run Code Online (Sandbox Code Playgroud)

如何BaseImpl print()从此重写函数中调用该函数?

用例是我想在重用现有实现的同时向此功能添加其他逻辑。

Ste*_*ris 6

@Egor 的答案有效,并且当委托给的类作为参数(依赖项注入)传递时应该适用。

但是,在我更具体的用例中(抱歉没有在我的问题中明确说明),实现是直接在委托定义中定义的。

class Derived(b: Base) : Base by BaseImpl()
Run Code Online (Sandbox Code Playgroud)

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

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

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

        ... do something extra
    }
}
Run Code Online (Sandbox Code Playgroud)

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


Ego*_*uba 5

由于Base是一个接口,因此您无法真正调用super它(类似于Java)。

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

class Derived(val b: Base) : Base by b {
    override fun print() {
        b.print()
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)