不同于 Java
,在 Kotlin
中,函数是一级公民。因此在 Kotlin
中的函数就拥有了很多不同于 Java
函数的高级特性。这篇文章就将介绍 kotlin
中函数的高级特性。
扩展函数
在 Kotlin
中,你可以从类的外部扩展出来的一个函数。代码示例如下:
// 定义一个判断字符串是否为 null 或者为空字符串的扩展函数
public fun String?.isNullOrEmpty(): Boolean {
return this == null || this.isEmpty()
}
fun test(str: String?) {
// 我们可以像 String 类的成员函数一样使用它
if(str.isNullOrEmpty()) {
...
}
}
扩展函数的实现也很简单,Kotlin
编译器会把 isNullOrEmpty
编译成 java 的静态方法,入参为 String
。它等同于如下的Java代码:
public static boolean isNullOrEmpty (String str) {
return str == null || str.length() <= 0;
}
但是扩展函数也有两点不足:
Kotlin
扩展不是真正的类成员,因此它无法被它的子类重写- 除此之外,扩展函数只能操作接收者的
Public
的属性
高级函数
在 Kotlin
中,函数可以视为一种类型。因此我们可以把函数作为参数,也可以作为返回值。像这种将函数用作参数或返回值的函数,我们把它叫做高阶函数。代码示例如下:
class Member(var name: String, var id: String) {
// 函数作为参数
// (String) -> Unit 其中 String 表示入参类型,Unit 表示返回值类型
fun methode(block: (String) -> Unit) {
block("")
}
// 函数作为返回值
fun methode1(): (String) -> Unit {
return ::method2
}
// 如果要表示挂起函数,需要加上 suspend
fun methode(block: suspend (String) -> Unit) {
CoroutineScope(Dispatchers.IO).launch {
block("")
}
}
}
为什么 Kotlin
需要引入高阶函数呢?答案是为了简化代码。考虑一下,如果没有高阶函数,我们就需要创建对应的接口来实现方法的回调。对应的 Java 代码如下所示:
interface Callback {
void call(String str);
}
void method(Callback callback) {
callback.call("");
}
带接收者的函数类型
在 kotlin
中还有一种特殊的函数类型,叫做带接收者的函数类型。初看名词可能有点懵,我们直接看代码:
// String 作为入参的函数类型
fun method(block: (String) -> Unit) {
}
// String.() -> Unit 就是带接收者的函数类型, String.() 表示入参带有 String;
// 因此 method1 其实等同于 method
fun method1(block: String.() -> Unit) {
}
fun test() {
// 不同点是 method 需要用 it 指定入参的 String
method() {
println(it)
}
// 而在 method1 中用 this 指定入参的 String
method1() {
println(this)
}
}
可以看到 带接收者的函数类型 就是帮我们做了一下简化,因为访问入参的属性时,this
是可以省略的,而 it
不可以。除此之外,示例中的 method1
完全等同于 method
。
构造函数
上面介绍完了 Kotlin
函数的高级特性,这里再补充一下 Kotlin
的构造函数。在 kotlin 中,构造函数声明如下所示:
//主构造函数
class Person(val name: String, val age: Int) {
//次构造函数
constructor(name: String, age: Int, id: String): this(name, age) {
}
}
在Kotlin中,在有默认参数值的方法中使用 @JvmOverloads 注解,就可以很方便地实现多个重载方法。最常使用的地方就是自定义 View,代码示例如下:
class MyView @JvmOverloads constructor(context:Context,
attributeSet: AttributeSet? = null,
defStyleAttr: Int = 0): View(context, attributeSet, defStyleAttr) {
}
它等价于如下 java 代码:
public class MyView extends View {
public MyView(Context context) {
this(context, null);
}
public MyView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}