编程高级Kotlin开发者

Kotlin中关键字'super'是如何工作的,与Java的使用有什么不同?在多个接口实现的情况下,何时会出现歧义性问题,如何解决?

用 Hintsage AI 助手通过面试

答案

在Kotlin中,关键字super用于调用超类或实现的接口中的方法或属性实现。与Java不同,Kotlin允许明确指定通过哪个接口或类调用方法实现,这在多个具有相同方法的接口之间出现"冲突"时尤其重要。

特点: 如果一个类实现了多个接口,其中定义了具有相同签名的方法,并且有默认实现,则必须明确指定使用哪种实现。

示例:

interface A { fun foo() = println("A") } interface B { fun foo() = println("B") } class C : A, B { override fun foo() { super<A>.foo() // 明确调用A.foo super<B>.foo() // 明确调用B.foo } }

这一点在Java中不直接支持(Java在Java 8之前不允许接口有字段/方法实现,即使在Java 8中,机制也不同)。

陷阱问题

"在Kotlin中可以通过多级继承访问超类方法的实现吗?"

  • 常见错误:以为可以通过中间类访问实现:super<Intermediate>.foo(),但并非如此——只能访问直接超类或实现该方法的接口。

示例:

open class Base { open fun foo() = println("Base") } open class Mid : Base() { override fun foo() { println("Mid"); super.foo() } } class Child: Mid() { override fun foo() { super.foo() // 将调用Mid.foo() // super<Base>.foo() — 编译错误 } }

因对该主题细节的不熟悉而导致的实际错误示例


故事

在一个大型项目中,接口LoggerAuditor都定义了方法record()。在实现同时继承这两个接口的类时,程序员没有明确重写record(),最终导致编译错误"Class must override public open fun record()"。不得不手动实现该方法,并明确委托给相应的接口。


故事

尝试通过多个中间层调用超类中实现的方法(例如,super<Base>.foo())时,编译出现错误。开发者不了解Kotlin的限制,无法理解为什么直接调用是不可能的。


故事

在API更新后,其中一个接口添加了与另一个接口相同的默认方法实现。旧代码由于实现冲突而无法再编译——不得不明确解决冲突,自己实现方法并选择在内部调用哪些超接口的实现。