• Kotlin笔记(三):扩展函数,运算符重载


    1. 扩展函数

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

     在Java中,如果我们需要统计字符串中的字母的数量的话,我们通常需要建立一个工具类,然后在工具类里面创建一个新的方法来实现该功能. 在Kotlin中,由于扩展函数功能的存在,我们可以直接在String类中扩展出新的方法,来实现该功能.

    1.1 扩展函数的语法

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

    fun ClassName.methodName(param1: Int, param2: Int): Int {
     	return 0
    }
    
    • 1
    • 2
    • 3

     相比于定义一个普通的函数,定义扩展函数只需要在函数名的前面加上一个ClassName.的语
    法结构,就表示将该函数添加到指定类当中了。

    1.2 扩展函数的实现

     文件名虽然并没有固定的要求,但是我建议向哪个类中添加扩展函数,就定义一个同名的Kotlin文件,这样便于你以后查找。当然,扩展函数也是可以定义在任何一个现有类当中的,并不一定非要创建新文件。不过通常来说,最好将它定义成顶层方法,这样可以让扩展函数拥有全局的访问域。

     现在在String.kt文件中编写如下代码:

    fun String.lettersCount(): Int {
     	var count = 0
     	for (char in this) {
     		if (char.isLetter()) {
     			count++
     		}
     	}
     	return count
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

     我们将lettersCount()方法定义成了String类的扩展函数,那么函数中就自动拥有了String实例的上下文。因此lettersCount()函数就不再需要接收一个字符串参数了,而是直接遍历this即可,因为现在this就代表着字符串本身。

    &emps;扩展函数在很多情况下可以让API变得更加简洁、丰富,更加面向对象。我们再次以String类为例,这是一个final类,任何一个类都不可以继承它,也就是说它的API只有固定的那些而已,至少在Java中就是如此。然而到了Kotlin中就不一样了,我们可以向String类中扩展任何函数,使它的API变得更加丰富。比如,你会发现Kotlin中的String甚至还有reverse()函数用于反转字符串,capitalize()函数用于对首字母进行大写,等等,这都是Kotlin语言自带的一些扩展函数。这个特性使我们的编程工作可以变得更加简便。

     不要被示例内容所局限,除了String类之外,你还可以向任何类中添加扩展函数,Kotlin对此基本没有限制。

    2. 运算符重载

     在Java中也存在运算符重载:用+来连接字符串,但是Java不支持自定义运算符重载功能. 而Kotlin允许我们将所有的运算符甚至其他的关键字进行重载,从而拓展这些运算符和关键字的用法。

    2.1 运算符重载语法

     运算符重载使用的是operator关键字,只要在指定函数的前面加上operator关键字,就可以实现运算符重载的功能了。但问题在于这个指定函数是什么?这是运算符重载里面比较复杂的一个问题,因为不同的运算符对应的重载函数也是不同的。比如说加号运算符对应的是plus()函数,减号运算符对应的是minus()函数。

     我们这里还是以加号运算符为例,如果想要实现让两个对象相加的功能,那么它的语法结构如下:

    class Obj {
     	operator fun plus(obj: Obj): Obj {
     	// 处理相加的逻辑
     	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

     在上述语法结构中,关键字operator和函数名plus都是固定不变的,而接收的参数和函数返
    回值可以根据你的逻辑自行设定。那么上述代码就表示一个Obj对象可以与另一个Obj对象相
    加,最终返回一个新的Obj对象。对应的调用方式如下:

    val obj1 = Obj()
    val obj2 = Obj()
    val obj3 = obj1 + obj2
    
    • 1
    • 2
    • 3

     这种obj1 + obj2的语法看上去好像很神奇,但其实这就是Kotlin给我们提供的一种语法糖,
    它会在编译的时候被转换成obj1.plus(obj2)的调用方式。

     了解了运算符重载的基本语法之后,下面我们开始实现一个更加有意义功能:让两个Money对
    象相加。

     首先定义Money类的结构,这里我准备让Money的主构造函数接收一个value参数,用于表示钱的金额。创建Money.kt文件,定义好了Money类的结构,接下来我们就使用运算符重载来实现让两个Money对象相加的功能:

    class Money(val value: Int) {
     	operator fun plus(money: Money): Money {
     		val sum = value + money.value
     	return Money(sum)
     	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

     可以看到,这里使用了operator关键字来修饰plus()函数,这是必不可少的。在plus()函数中,我们将当前Money对象的value和参数传入的Money对象的value相加,然后将得到的和传给一个新的Money对象并将该对象返回。这样两个Money对象就可以相加了,就是这么简单。

     但是,Money对象只允许和另一个Money对象相加,有没有觉得这样不够方便呢?或许你会觉
    得,如果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)
     	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

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

    在这里插入图片描述

     注意,最后一个a in b的语法糖表达式对应的实际调用函数是b.contains(a),a、b对象的顺序是反过来的。这在语义上很好理解,因为a in b表示判断a是否在b当中,而b.contains(a)表示判断b是否包含a,因此这两种表达方式是等价的。

  • 相关阅读:
    构建简单的梯度提升决策树(GBDT)模型:MATLAB 实现详解
    2016年新华三杯复赛实验试题
    Android ADB 常用命令及详解
    修改docker ip网段
    k8s集群使用Yaml部署Nacos集群
    acwing算法基础之数据结构--并查集算法
    嵌入式 Linux 入门(七、Linux 下的环境变量)
    面试Java高级工程师之Redis总结
    低代码平台对于开发者来说可以解决哪些问题?
    Nginx的日志格式
  • 原文地址:https://blog.csdn.net/u010483016/article/details/133851549