调用(基本)委托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
的主要构造函数只能在内部使用,因此库的调用者无法实例化这个类,因此被迫使用Derived
。 Derived
现在可以调用委托给内部的类,并添加额外的行为,而不允许调用者通过不同的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
希望这会帮助你。
- android – 运行应用程序失败,错误“com.android.builder.dexing.DexArchiveMergerException:无法合并dex’
- 如何避免与Dagger 2的循环依赖?