• 扩展函数和运算符重载


    扩展函数和运算符重载

    扩展函数

    • 扩展函数表示在不改变某个类的源代码的情况下,仍然可以打开这个类,向该类中添加新的函数
    • 为了能够更好的理解扩展函数的功能,先来思考一个问题:
    • 给定一个字符串,这个字符串由字母,数字,特殊符号组成,我们想要统计这个字符串当中字母的个数
    • 可以这样写:
    /**
     * 定义一个单例类,在其中编写对应的方法 
     */
    object StringUtil {
        fun letterCount(str: String) : Int {
            var count = 0
            for(char in str) {
                if(char.isLetter()) {
                    count++
                }
            }
            return count
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 现在我们想要统计一个字符串的字母数量的时候只需要写出下面这类代码即可
    val str = "ABC123&&abv"
    println(StringUtil.letterCount(str))
    
    • 1
    • 2
    • 但是扩展函数可以帮助我们将letterCount()函数添加到String类当中
    • 扩展函数的语法结构:
    fun ClassName.methodName(para1: Int, para2: Int) : Int {
        
    }
    
    • 1
    • 2
    • 3
    • 相比于定义一个普通的函数,定义扩展函数只需要在函数名的前面加上一个ClassName.的语法结构,这表示将该函数添加到指定的类当中了
    • 那么接可以将刚才定义的统计字符串字母数量的方法添加到String类当中了
    • 由于我们想要给String类添加一个扩展函数,所以我们需要先创建一个String.kt文件.
    • 文件名没有固定的要求,只是为了方便知道这个文件中都是哪个类的扩展函数,所以说给那个类添加扩展函数,就直接将扩展函数编写到这个类的同名.kt文件夹中
    • 通常来说扩展函数会定义成为顶层方法,因为这样可以让扩展函数用于全局的访问域.
    • 现在在String.kt文件当中编写扩展函数
    fun String.letterCount() : Int{
        var count = 0
        for(char in this) {
            if(char.isLetter()) {
                count++
            }
        }
        return count
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 注意两份代码的变化,我们将letterCount()方法定义成为了String类的扩展函数,那么在函数当中就自动拥有了该String实例的上下文.
    • 因此letterCount()函数就不需要再接受一个String类型的参数了,直接遍历this本身即可,因为现在this就代表着字符串本身
    • 定义好扩展函数之后我们代码就可以这样写了
    println("ABC123&&abv".letterCount())
    
    • 1
    • 这样子看上去就好像String类中自带了letterCount()方法一样.这个就是扩展函数的特点.

    运算符重载

    • 运算符重载是Kotlin提供的一个比较有意思的语法糖概念
    • 在Kotlin当中允许我们对所有的运算发加上一些关键字做重载
    • 比如像+这个操作符,当使用两个数字进行+操作的时候代表对这个数字进行求和,当对两个字符串进行+操作的时候代码将这两个字符串进行拼接
    • 在Kotlin当中给我们提供了运算符重载机制,让我们能够实现对两个对象进行+操作
    • 但是我们在进行运算符重载的时候,一定要考虑它的意义性,比如我们让两个Student类进行相加好像没有什么意义,但是我们让两个Money类进行相加就说明我们想求出钱的总金额,这样才有意义
    • 运算符重载的基本语法:
    • 运算符重载使用的是operator关键字,只要在指定的函数前面加上operator关键字就可以实现运算符的重载了
    • 像+运算符的指定函数就是plus()函数
    class obj {
        operator fun plus(obj: obj, 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
    • 虽然看上去比较神奇,但是实际上这是kotlin提供的一种语法糖,上述代码在编译的过程当中会自动转换成为:obj1.plus(obj2)的调用方式
    • 现在来实现一个两个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对象就可以进行相加了
    val money1 = Money(5)
    val money2 = Money(10)
    val money3 = money1 + money2
    println(money3.value)
    
    • 1
    • 2
    • 3
    • 4
    • 上述代码打印出来的结果一定是15
    • 现在我们的+操作符可以进行Money对象之间进行相加了,当我们还想让+操作符和数字也能进行相加我们还可以继续重载
    class Money(val value: Int) {
        operator fun plus(money: Money) : Money {
            val sum = value + money.value
            return Money(sum)
        }
         operator fun plus(value: Int) : Money {
            val sum = value + value
             return Money(sum)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • kotlin允许我们进行重载的运算符和关键字多达十几个,在下面的表当中就列举出了所有常用的可重载运算符和关键字对应的语法糖表达式,以及它们要被转换成的实际函数
    • 如果想要重载其中的某一种运算符或者关键字,只需要按照上述代码的写法进行编写即可

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oi8NRXh9-1669538864211)(C:/Users/zhengbo/%E6%88%91%E7%9A%84%E5%AD%A6%E4%B9%A0/Typora%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E5%AE%89%E5%8D%93/image-20221127164515782.png)]

  • 相关阅读:
    Java安全第一篇 | 反射看这一篇就够了
    从零开始打造一款基于SpringBoot+SpringCloud的后台权限管理系统
    PHP安全问题:远程溢出、DoS、safe_mode绕过漏洞
    String 和 Char[ ] 作为方法参数的值传递问题
    Golang 语言接口的定义与实现
    1-多媒体通信概述
    【CTO变形记】整体系统思维-从现象到本质
    【Redis】共同关注列表与基于Feed流的关注消息滚动分页推送的实现
    Python统计学01——数据可视化
    springboot+knife4j初体验
  • 原文地址:https://blog.csdn.net/weixin_45809829/article/details/128066297