目录
5.6 Kotlin 课堂:扩展函数的运算符重载
很开心,又要开始学习 Kotlin 的新知识了。通过前面几章内容的锻炼,相信现在的你已经可以颇为熟练地使用Kotlin 来编写代码了。现在是时候去探究一些 Kotlin 更加深入的内容了,那么赶快进入本章的Kotlin 课堂当中吧。
5.6.1 大有用途的扩展函数
不少现代高级编程语言中有扩展函数这个概念,Java 却一直以来都不支持这个非常有用的功 能,这多少会让人有些遗憾。但值得高兴的是,Kotlin 对扩展函数进行了很好的支持,因此这个 知识点是我们无论如何都不能错过的。
首先看一下什么是扩展函数。扩展函数表示即使在不修改某个类的源码的情况下,仍然可以打 开这个类,向该类添加新的函数。
为了帮助你更好地理解,我们先来思考一个功能。一段字符串中可能包含字母、数字和特殊符号等字符,现在我们希望统计字符串中字母的数量,你要怎么实现这个功能呢?如果按照一般 的编程思维,可能大多数人会很自然地写出如下函数:
object StringUtil {
fun lettersCount(str: String): Int {
var count = 0
for (char in str) {
if (char.isLetter()) {
count++
}
}
return count
}
}
这里先定义了一个 StringUtil 单例类,然后在这个单例类中定义了一个 lettersCount() 函 数,该函数接收一个字符串参数。在 lettersCount() 方法中,我们使用 for-in 循环去遍历字符串中的每一个字符。如果该字符是一个字母的话,那么就将计数器加 1,最终返回计数器的 值。
现在,当我们需要统计某个字符串中的字母数量时,只需要编写如下代码即可:
val str = "ABC123xyz!@#"
val count = StringUtil.lettersCount(str)
这种写法绝对可以正常工作,并且这也是Java 编程中最标准的实现思维。但是有了扩展函数之 后就不一样了,我们可以使用一种更加面向对象的思维来实现这个功能,比如说将 lettersCount() 函数添加到 String 类当中。
下面我们先来学习一下定义扩展函数的语法结构,其实非常简单,如下所示:
fun ClassName.methodName(param1: Int, param2: Int): Int {
return 0
}
相比于定义一个普通的函数,定义扩展函数只需要在函数名的前面加上一个 ClassName. 的语法结构,就表示将该函数添加到指定类当中了。
了解了定义扩展函数的语法结构,接下来我们就尝试使用扩展函数的方式来优化刚才的统计功能。
由于我们希望向 String 类中添加一个扩展函数,因此需要先创建一个 String.kt 文件。文件名虽 然并没有固定的要求,但是我建议向哪个类中添加扩展函数,就定义一个同名的 Kotlin 文件,这样便于你以后查找。当然,扩展函数也是可以定义在任何一个现有类当中的,并不一定非要创 建新文件。不过通常来说,最好将它定义成顶层方法,这样可以让扩展函数拥有全局的访问域。
现在在 String.kt 文件中编写如下代码:
fun String.lettersCount(): Int {
var count = 0
for (char in this) {
if (char.isLetter()) {
count++
}
}
return count
}
注意这里的代码变化,现在我们将 lettersCount() 方法定义成了 String 类的扩展函数,那么函数中就自动拥有了 String 实例的上下文。因此 lettersCount() 函数就不再需要接收一 个字符串参数了,而是直接遍历 this 即可,因为现在 this 就代表着字符串本身。
定义好了扩展函数之后,统计某个字符串中的字母数量只需要这样写即可:
val count = "ABC123xy