/* Java */
char c = StringUtilKt.lastChar("Java"); // <1>
该扩展函数被声明为顶级函数 ,因此编译为静态方法
<1> 可以从 Java 中静态导入 lastChar 方法
从而简化使用 , 只需 lastChar("Java") 即可
注意使用的导入方式"import static xxx"
kotlin复制代码
import static strings.StringFunctions.lastChar; // <1>
public class Example {
public static void main(String[] args){
System.out.println(lastChar("Java")); // <1>
}
}
扩展函数的静态特性 还意味着子类中不能重载扩展函数
1.1.2 扩展函数无法重载
在 Kotlin 中,方法重载与成员函数一样有效 ,但不能重载扩展函数
<1> 假设有两个类: View 和 Button
Button 是 View 的子类,它重载父类中的 click 函数
<2> 要实现这一点,可以使用 open 修饰符标记View和click , 以允许重载
并使用 override 修饰符在子类中提供一个实现
kotlin复制代码
open class View {
open fun click() = println("View clicked") // <2>
}
class Button: View() { // <1>
override fun click() = println("Button clicked") // <2>
}
如果你声明一个 View 类型的变量
<1> 那么你就可以在该变量中存储 Button 类型的值
因为 Button 是 View 的子类型
<2> 如果在该变量上调用常规方法(如 click)
而该方法在 Button 类中被重载 ,则将使用 Button 类的重载实现
kotlin复制代码
fun main() {
val view: View = Button() // <1>
view.click() // <2>
// Button clicked
}
但对于扩展函数来说,情况并非如此
扩展函数不是类的一部分 ,它们是在类的外部声明的
比如, 在 View 和 Button 类之外
定义 View.showOff() 和 Button.showOff() 扩展函数
即使可以为基类及其子类 定义具有相同名称和参数类型的扩展函数
<1> 但调用的函数取决于变量声明的静态类型 , 该类型在编译时确定
在对 view 变量调用 showOff 时,即使值的实际类型是 Button
也会调用View类型的showOff方法 ,因为view变量的编译时类型是"View"
kotlin复制代码
fun View.showOff() = println("I'm a view!")
fun Button.showOff() = println("I'm a button!")
fun main() {
val view: View = Button()
view.showOff() // <1>
// I'm a view!
}
回忆一下上面所说的扩展函数在 Java 中被编译为静态函数
接收器对象是第一个参数 , Java 也会以同样的方式调用指定类型的扩展函数
kotlin复制代码
/* Java */
class Demo {
public static void main(String[] args) {
View view = new Button();
ExtensionsKt.showOff(view);
// I'm a view!
}
}