Kotlin学习 4 -- 扩展函数和运算符重载

本篇文章主要介绍以下几个知识点:

  • 扩展函数
  • 运载符重载
    内容参考自第一行代码第3版
SUMMER DAY (图片来源于网络)

1. 扩展函数

扩展函数是指即使在不修改某个类的源码的情况下,仍然可以打开这个类,向该类添加新的函数。

考虑要实现一个统计字符串中字母的数量的功能,则可定义如下函数:

object StringUtil {
    fun lettersCount(str: String): Int {
        var count = 0
        for (char in str) {
            if (char.isLetter()) {
                count++
            }
        }
        return count
    }
}

调用方式如下:

fun main() {
    val str = "ABC123xyz!@#"
    val count = StringUtil.lettersCount(str) // 统计字符串str中的字母数量
    println(count)
}

上述写法是 Java 编程的标准实现思维,但有了扩展函数后,可以用一种更加面向对象的思维来实现这个功能。

定义扩展函数的语法结构如下:

// 定义扩展函数只需在函数名的前面加上一个 ClassName. 的语法结构,
// 就表示将该函数添加到指定类了
fun ClassName.methodName(param1: Int, param2: Int): Int {
    return 0
}

接下来把 lettersCount() 函数添加到 String 类中,如下:

fun String.lettersCount(): Int {
    var count = 0
    for (char in this) {
        if (char.isLetter()) {
            count++
        }
    }
    return count
}

调用方式如下:

fun main() {
    val count = "ABC123xyz!@#".lettersCount()
    println(count)
}

注:扩展函数可以定义在任何一个现有类中,但最好把它定义成顶层方法,这样可以让扩展函数拥有全局的访问域。

小结:扩展函数在多数情况下可以让 API 更加简洁、丰富,更加面向对象。Kotlin 自带的一些扩展函数如用于反转字符串的 reverse() 函数,用于对首字母大写的 capitalize() 函数等,使编码更加简便了。

2. 运载符重载

在 Kotlin 中,可以将如 + - * / % ++ -- 等所有运算符或其他的关键字进行重载,从而扩展这些运算符和关键字的用法。

实现运算符重载只要在指定函数的前面加上 operator 关键字,不同的运算符对应的重载函数也不同:

部分语法糖表达式和实际调用函数对照表

接下来以加号运算符为例,实现两个对象相加的功能,其语法结构如下:

class Obj {
    // 关键字 operator 和 函数名 plus 固定不变,接收的参数和函数返回值自行设定,
    // 这里表示一个 Obj 对象与另一个 Obj 对象相加,返回一个新的 Obj 对象
    operator fun plus(obj: Obj): Obj {
        // 处理相加逻辑
    }
}

// 调用方式
val obj1 = Obj()
val obj2 = Obj()
val obj3 = obj1 + obj2

下面实现两个 Money 对象相加,首先定义个 Money 类如下:

// value 表示金额
class Money(val value: Int)

接着使用运算符重载来实现让两个 Money 对象相加的功能:

class Money(val value: Int) {
    operator fun plus(money: Money): Money {
        val sum = value + money.value
        return Money(sum)
    }
}

调用结果如下:

fun main() {
    val money1 = Money(20)
    val money2 = Money(18)
    val money3 = money1 + money2
    println(money3.value) // 打印结果是:38
}

若要让 Money 对象可以直接和数字相加,则可修改如下(Kotlin 允许对同一个运算符进行多次重载):

class Money(val value: Int) {
    operator fun plus(money: Money): Money {
        val sum = value + money.value
        return Money(sum)
    }

    operator fun plus(newValue: Int): Money {
        val sum = value + newValue
        return Money(sum)
    }
}

这样 Money 对象就可以和数字相加了:

fun main() {
    val money1 = Money(20)
    val money2 = money1 + 18
    println(money2.value) // 打印结果是:38
}

上表中最后一个 a in b 语法糖表达式对应的实际调用函数是 b.contains(a),Kotlin 中的 String 类有对 contains() 函数进行重载,如判断 “Wonderful” 字符串中是否含有 “Won” 字符串时:

if("Wonderful".contains("Won")) { }

而借助重载的语法糖表达式,可这样写:

if("Won" in "Wonderful") { }

小结:运算符重载用得好的话,可以玩出很多花样。

本篇文章就介绍到这。

你可能感兴趣的:(Kotlin学习 4 -- 扩展函数和运算符重载)