调用(基本)委托function时,从内部使用类委托覆盖

当覆盖类委托实现的接口方法时,是否可以从一个覆盖函数中调用通常委派给的类? 与使用inheritance时的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) { val b = BaseImpl(10) Derived(b).print() // prints 10 } 

请注意,覆盖工作正如您所期望的那样:编译器将使用您的覆盖实现,而不是代理对象中的那些实现。

 override fun print() { ... } 

如何从这个重写的函数中调用BaseImpl print()函数?

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

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

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

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

@叶戈尔的答案工作,并应该适合当委托类作为paremeter(dependency injection)传递。

然而,在我的更具体的用例(道歉没有在我的问题中明确表示),实施是直接定义在代表团的定义。

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

在这种情况下,叶戈尔的答案是行不通的,需要一个更复杂的方法。 下面的实现可以用来防止实现隐藏,以便调用者不能修改它。 例如,在我的具体用例中,我创建了一个聚合根,并希望保护内部不variables。

 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的主要构造函数只能在内部使用,因此库的调用者无法实例化这个类,因此被迫使用DerivedDerived现在可以调用委托给内部的类,并添加额外的行为,而不允许调用者通过不同的Base实现。

您只能在Kotlin中使用super来访问超类,没有接口或其他奇怪的东西(请记住 – Kotlin正在JVM上运行)。 但是,如果将衍生实例存储在一个variables中,就像Egor在他的回答中所建议的那样,这是绝对没问题的 。

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

 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) { val d = Derived() db // does not work, compiler error d.print() // prints 10 } 

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

希望这会帮助你。