MST

星途 面试题库

面试题:Kotlin扩展函数与成员函数的优先级及冲突处理

当Kotlin类的成员函数与扩展函数具有相同的签名时,系统如何确定调用哪个函数?请详细解释优先级规则。如果希望在特定情况下调用扩展函数而非成员函数,应该怎么做?编写一个复杂的示例,展示存在多个同名函数(成员函数和扩展函数)时的调用逻辑及处理方式。
21.2万 热度难度
编程语言Kotlin

知识考点

AI 面试

面试题答案

一键面试
  1. 优先级规则
    • 当Kotlin类的成员函数与扩展函数具有相同的签名时,成员函数具有更高的优先级。也就是说,如果类中定义了一个与扩展函数签名相同的成员函数,调用该函数时会优先调用成员函数。这是因为成员函数是类定义的一部分,与类的紧密程度更高,而扩展函数本质上是一种通过静态方法实现的对类的“外部扩展”。
  2. 调用扩展函数而非成员函数的方法
    • 可以通过将对象转换为其超类型(如果超类型没有同名的成员函数),然后调用扩展函数。例如,如果有一个类SubClass继承自SuperClassSubClass有一个成员函数funcSuperClass有一个针对SuperClass的扩展函数func,那么将SubClass对象转换为SuperClass类型后调用func,就会调用到扩展函数。
  3. 复杂示例
open class Animal {
    open fun makeSound() {
        println("Animal makes a sound")
    }
}

class Dog : Animal() {
    override fun makeSound() {
        println("Dog barks")
    }

    fun makeSound(sound: String) {
        println("Dog makes sound: $sound")
    }
}

fun Animal.makeSound(sound: String) {
    println("Animal makes sound: $sound")
}

fun main() {
    val dog = Dog()
    dog.makeSound() // 调用Dog类的成员函数makeSound(),输出 "Dog barks"
    dog.makeSound("woof woof") // 调用Dog类的成员函数makeSound(String),输出 "Dog makes sound: woof woof"

    (dog as Animal).makeSound("generic sound") // 将Dog对象转换为Animal类型后调用扩展函数makeSound(String),输出 "Animal makes sound: generic sound"
}

在上述示例中:

  • 首先定义了Animal类及其makeSound成员函数。
  • Dog类继承自Animal,重写了makeSound成员函数,并新增了一个带参数的makeSound成员函数。
  • 同时定义了针对Animal类的扩展函数makeSound(String)
  • main函数中,直接调用dog.makeSound()调用的是Dog类重写的成员函数;调用dog.makeSound("woof woof")调用的是Dog类带参数的成员函数;而将dog转换为Animal类型后调用makeSound("generic sound"),调用的是扩展函数。