Kotlin学习知识点整理-进阶篇-05

Kotlin知识点整理进阶

本文是我在学习Kotlin的过程当中整理的一些知识点,若有错误,欢迎指正markdown

1、运算符重载

运算符重载使用的是 operator 关键字
以加号运算符为例,实现让两个对象相加的功能,语法结构以下:app

class OBj{
    operator fun plus(obj: Obj): Obj{
     //处理相加逻辑
    } 
}
//调用方法以下
val obj1 = Obj()
val obj2 = Obj()
val obj3 = obj1 + obj2 
复制代码
语法糖表达式和实际调用函数对照表
语法糖表达式 实际调用函数
a + b a.plus(b)
a - b a.minus(b)
a * b a.times(b)
a / b a.div(b)
a % b a.rem(b)
a++ a.inc()
a-- a.dec()
+a a.unaryPlus()
- a a.unaryMinus()
! a a.not()
a == b a.equals(b)
a > b a.compareTo(b)
a < b
a >= b
a <= b
a..b a.rangeTo(b)
a[b] a.get(b)
a[b] = c a.set(b, c)
a in b b.contains(a)

注:最后一个 a in b,表示判断 a 是否在 b 中,而 b.contains(a) 表示判断 b 是否包含 a,所以这两种表达方式是等价的。函数

2、扩展函数 + 运算符重载使用示例

下面来看个示例,如今准备用扩展函数+运算符重载来实现一个让字符串重复打印指定次数的功能,相似 str * n这种形式,代码以下:oop

operator fun String.tines(n : Int) : String {
    val builder = StringBuilder()
    repeat(n) {
        builder.append(this)
    }
    return builder.toString
}
复制代码

operator关键字是必不可少的,接着参考上面的表可知函数名是 tines,而后因为咱们是给字符串添加的扩展函数,故在方法名前面加上了 String ,最后借助 repeat() 将字符串重复 n 次。post

如今,字符串就有了能够和数字相乘的能力,好比执行以下代码:学习

val str = "abc" * 3
println(str)

//最终打印结果就是:abcabcabc
复制代码

其实 Kotlin 中的 String 类中已经提供了一个 repeat() 函数,因此咱们还能够简化上面的函数,以下:ui

operator fun String.tines(n : Int) = repeat(n)
复制代码

3、高阶函数

一、定义高阶函数

定义:若是一个函数接收另外一个函数做为参数,或者返回值的类型是另外一个函数,那么该函数就称为高阶函数。this

定义一个函数类型:spa

(String, Int) -> Unit
复制代码

-> 左边的部分就是用来声明该函数接收什么参数的,多个参数之间使用逗号隔开,若是不接受任何参数,写一对空括号就能够。
-> 右边的部分用于声明该函数的返回值是什么类型,若是没有返回值就使用 Unit,它大体至关于Java中的 voidcode

定义一个高阶函数:

fun example(func: (String, Int) -> Unit){
    func("hello",123)
}
复制代码

用途:高阶函数容许让函数类型的参数来决定函数的执行逻辑。即便是用一个高阶函数,只要传入不一样的函数类型参数,那么它的执行逻辑和最终的返回结果就多是彻底不一样的。
咱们来看一个示例:

fun StringBuilder.build(block: StringBuilder.() -> Unit): StringBuilder{
    block()
    return this
} 
复制代码

咱们给 StringBuilder 定义了一个扩展函数 build ,它接收一个函数类参数。而且若是在函数类型前面加上了 ClassName. 的语法结构,就表示这个函数类型是定义在哪一个类中的。故这里的参数加上了 StringBuilder. 的语法结构,就表示这个函数类型是定义在 StringBuilder 这个类中的,这样的做用是当咱们调用 build 函数时传入的 Lambda 表达式能够自动拥有 StringBuilder 的上下文,相似于 apply 函数,不用的地方在于 apply 能够做用到全部类上,这里的只能做用在 StringBuilder 类上。
用法以下:

val result = StringBuilder.build{
    append("Start here \n")
    append("str1 str2 \n")
    append("End here")
}
复制代码

二、内联函数

内联函数主要是为了解决运行Lambda表达式时带来的运行时开销。
内联函数用法 在定义高阶函数时加上 inline 关键字,以下所示:

inline fun num1AndNum2(num1:Int,num2:Int,operation: (Int,Int) -> Int) : Int{
    val result = operation(num1, num2)
    return result
}
复制代码

noinline 只想内联其中一个Lambda表达式:

inline fun num1AndNum2(block1 : () -> Unit, noinline block2 : () -> Unit){
}
复制代码

Q:为什么Kotlin要提供一个 noinline 关键字来排除内联功能?
A:内联函数的函数类型参数在编译时会进行代码替换,所以它没有真正的参数属性。非内联的函数类型参数能够自由地传递给其它任何函数,由于它就是一个真实的参数,而内联的函数类型参数只容许传递给另外一个内联函数。
(补充:内联函数与非内联函数还有一个重要的区别:内联函数所引用的Lambda表达式中是能够使用 return 关键字来进行函数返回的,而非内联函数只能局部返回)

上一篇 Kotlin学习知识点整理-进阶篇-04

参考资料:
《第一行代码(第三版)》

相关文章
相关标签/搜索