Kotlin:概念:7. Kotlin 函数介绍:扩展函数,中缀函数,运算符函数,带有varrag输入的函数,内联函数

这里介绍Kotlin的不同种类函数,包括:一般的函数表达方式,扩展函数,中缀函数,运算符函数,带有varrag输入的函数,内联函数。


文章目录

  • Kotlin:概念:7. Kotlin 函数介绍:扩展函数,中缀函数,运算符函数,带有varrag输入的函数,内联函数
    • 1 一般函数
    • 2 扩展函数
    • 3 中缀函数 (infix function)
    • 4 运算符重载函数 (Operator Functions)
    • 5 vararg
    • 6 内联函数

1 一般函数

直接上一些例子,都挺一目了然的。

fun printMessage(message: String): Unit {                               println(message)
}
// 一个简单的函数,它接受一个 String 类型的参数并返回 Unit (即没有返回值)。fun printMessageWithPrefix(message: String, prefix: String = "Info") {  println("[$prefix] $message")
}
// 这个函数第二个参数带默认值,其返回类型被省略,实际上和上面这个函数一样,返回 Unit。fun sum(x: Int, y: Int): Int {                                          return x + y
}
// 返回整数的函数。fun multiply(x: Int, y: Int) = x * y
// 返回整数(推断)的单表达式函数。(single-expression function)fun main() {printMessage("Hello")                                               // 5                    printMessageWithPrefix("Hello", "Log")                              // 6printMessageWithPrefix("Hello")                                     // 7printMessageWithPrefix(prefix = "Log", message = "Hello")           // 8println(sum(1, 2))                                                  // 9println(multiply(2, 4))                                             // 10
}

2 扩展函数

我们以如何对一个字符串计数为例,java的方式可以这么写:

object StringUtil{fun letterCount(str:String):Int{var count=0for(char in str){if(char.isLetter()){count++}}return count}
}fun main() {val str="ABC123xyz!@#"val count=StringUtil.letterCount(str)
}

对于Kotlin,我们可以使用一种更加面向对象的思维实现-将方法添加到现有类中(扩展函数)。

fun String.letterCount(): Int {var count = 0for (char in this) {if (char.isLetter())count++}return count
}val count1="ABC123xyz!@#".letterCount()

3 中缀函数 (infix function)

中缀函数为为成员函数或者扩展函数,并且只有一个参数、参数不能是可变参数且不能有默认值, 并且使用infix修饰。

对于Kotlin的map的使用就涉及到中缀函数:

fun main(args: Array<String>) {val map = mapOf(1 to "one", 2 to "two")map.map(::println)
}
//result:
//1=one
//2=two

val map = mapOf(1 to "one", 2 to "two")里的to就是一个infix function。其源码实现:

public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)

接下来还罗列了一些中缀函数的例子:

fun main() {infix fun Int.times(str: String) = str.repeat(this)        // 基于 Int 定义了一个中缀函数println(2 times "Bye ")                                    // 返回 Bye Byeval pair = "Ferrari" to "Katrina"                          println(pair)// 上面的例子可以看到,to 本来就是一个中缀函数,实现的就是 Pair 的功能infix fun String.onto(other: String) = Pair(this, other)   val myPair = "McLaren" onto "Lucas"println(myPair)// 这是我们自定义的 to 的调用的实现val sophia = Person("Sophia")val claudia = Person("Claudia")sophia likes claudia                                       // 中缀表示法也适用于成员函数(方法)
}class Person(val name: String) {val likedPeople = mutableListOf<Person>()infix fun likes(other: Person) { likedPeople.add(other) }
}

4 运算符重载函数 (Operator Functions)

Kotlin允许我们将所有的运算符,关键字进行重载,扩展他们的用法。

operator fun Int.times(str: String) = str.repeat(this)
println(2 * "Bye ")
// times() 的运算符符号是 *,因此您可以使用 2 * "Bye" 调用该函数。operator fun String.get(range: IntRange) = substring(range)
// 运算符函数允许对字符串进行轻松的范围访问。
val str = "Always forgive your enemies; nothing annoys them so much."
println(str[0..14])
// get() 运算符启用括号访问语法。class Money(val value: Int) {operator fun plus(money: Money): Money {val sum = value + money.valuereturn Money(sum)}
}fun main() {val money1=Money(5)val money2=Money(10)val money3=money1+money2println(money3.value)// 15
}

更复杂的,运算符多重重载:

class Money(val value: Int) {operator fun plus(money: Money): Money {val sum = value + money.valuereturn Money(sum)}operator fun plus(newValue: Int): Money {val sum = value + newValuereturn Money(sum)}
}fun main() {val money1 = Money(5)val money2 = Money(10)val money3 = money1 + money2val money4 = money3 + 20println(money3.value)   //15println(money4.value)   //35
}

这里附上语法糖表达式和实际调用函数对照表:

语法糖表达式 实际调用函数
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.rangeTo(b)
a[b] a.get(b)
a[b] = c a.set(b,c)
a in b b.contains(a)

5 vararg

Varargs 允许我们通过用逗号分隔参数来传递任意数量的参数。

fun printAll(vararg messages: String) {                            for (m in messages) println(m)
}
// 可变参数修饰符将参数转换为可变参数。
printAll("Hello", "Hallo", "Salut", "Hola", "你好")
// 允许使用任意数量的字符串参数调用 printAll。fun printAllWithPrefix(vararg messages: String, prefix: String) { for (m in messages) println(prefix + m)
}
printAllWithPrefix("Hello", "Hallo", "Salut", "Hola", "你好",prefix = "Greeting: "
)
// 我们也可以在可变参数之后添加另一个相同类型的参数。fun log(vararg entries: String) {printAll(*entries)
}
// 在运行时,可变参数只是一个数组。 要将其传递到可变参数参数中,请使用特殊的扩展运算符 *,它允许我们传入 *entries(String 的 vararg)而不是 Array<String>。

6 内联函数

当一个函数被内联 inline 标注后,在调用它的地方,会把这个函数方法体中的所有代码移动到调用的地方。比如如下代码:

// 在 main() 中调用 makeTest()
fun main() {Log.i("zc_test", "main() start")makeTest()Log.i("zc_test", "main() end")
}
// 内联函数 makeTest()
private inline fun makeTest() {Log.i("zc_test", "makeTest")
}

使用 inline 编译成 java 的代码

public final void main() {Log.i("zc_test", "main() start");int $i$f$makeTest = false;Log.i("zc_test", "makeTest");Log.i("zc_test", "main() end");
}

当 makeTest() 不在被 inline 修饰时, 被编辑成 java 的代码为:

public final void main() {Log.i("zc_test", "main() start");this.makeTest();Log.i("zc_test", "main() end");
}

可以看到,当 makeTest() 被inline 修饰时, 在 main() 中原来调用 makeTest() 的地方被替换成了 makeTest() 里面的代码。

什么时候应该使用内联函数?

每次使用集合操作时,我们都会使用内联函数,比如说 map,filter 等。如此一来可以更好地实现干净和快速的函数式编程。

val newList = listOf(1, 2, 3, 4).map { it * 2 }// compiles to
val temp: MutableList<Int> = mutableListOf()
for (x in listOf(1, 2, 3, 4)) {temp.add(x * 2)
}val newList = temp.toList()

inline 能带来的性能提升,往往是在参数是 lambda 的函数上。

一起来学Kotlin:概念:7. Kotlin 函数介绍:扩展函数,中缀函数,运算符函数,带有varrag输入的函数相关推荐

  1. Sql中TO_DAYS,DATE_SUB等时间函数介绍

    Sql中TO_DAYS,DATE_SUB等时间函数介绍 TO_DAYS 获取当前时间 DATE_SUB(date,INTERVAL expr type)函数 DATEDIFF() 函数 ADDDATE ...

  2. 译码器和数据选择器的使用-实现多输入逻辑函数

    译码器和数据选择器的使用 实例1:使用译码器和门电路实现逻辑函数 使用74138译码器和门电路实现逻辑函数L=AB+BC+ACL=AB+BC+ACL=AB+BC+AC 74138译码器介绍以及与log ...

  3. scipy.optimize函数介绍

    scipy.optimize模块使用 前言 一.scipy.optimize模块包含什么? 二.使用步骤 1.函数介绍 前言 简单使用scipy.optimize,训练逻辑回归损失函数,得到权值. 一 ...

  4. Kotlin系列四:标准函数、扩展函数、高阶函数、内联函数

    目录 一 标准函数 1.1 作用域函数 1.1.1 let 1.1.2  with 1.1.3 run 1.1.4 apply 1.1.5 also 1.1.6 takeIf 与 takeUnless ...

  5. Kotlin读书笔记之内联函数、扩展函数、匿名函数、lambda

    本文主要涉及内联函数.扩展函数.lambada以及匿名函数等.作为读书笔记对于细节深入没有过多的扩展,后续将对于各个知识点作进一步的研度.本文的内容主要是参考官方教程以及博客内容,作为读书笔记以及后续 ...

  6. android kotlin面试题,Kotlin面试25题

    大家好,这一期呢,我们谈一下kotlin的面试题. 第1题,什么是kotlin? kotlin是静态类型的编程语言,运行于jvm之上. 第2题, 是谁开发了kotlin? kotlin是由jetbra ...

  7. 【Kotlin学习】Kotlin中的反射

    反射:在运行时对kotlin对象进行自省 反射是一种在运行时动态访问对象属性和方法的方式,而不需事先确定这些属性是什么.一般来说当你访问一个对象的方法或者属性时,程序的源代码会因用一个具体的声明,编译 ...

  8. Kotlin Jetpack 实战: Kotlin 基础 | 开发者说·DTalk

    本文原作者: 朱涛,原文发布于: 朱涛的自习室 https://mp.weixin.qq.com/s/MSbSPeWNlM5PJCFmLg2SVQ 背景 近几年,Android 相关的新技术层出不穷. ...

  9. 【Kotlin】Kotlin 领域特定语言 DSL 原理 二 ( 中缀表达式 )

    文章目录 I . 中缀表达式 ( 中缀调用 ) II . 中缀表达式 ( 中缀调用 ) 示例代码 I . 中缀表达式 ( 中缀调用 ) 1 . 中缀表达式作用 : 中缀表达式是 Kotlin 领域特定 ...

最新文章

  1. yolo标注的数据清洗
  2. IBASE Header change - access sequence
  3. 裤子尺码对照表eur40_弄明白这两个问题,你就知道内衣尺码怎么区分
  4. 牛客网【每日一题】5月8日题目精讲 codeJan与旅行
  5. 服务器mysql如何添加数据库文件,如何在使用MySQL作为嵌入式服务器时创建数据库文件...
  6. T-SQL逻辑处理之表运算符
  7. Web后端学习笔记 Flask(13)memcached
  8. LeetCode 139. 单词拆分(动态规划)
  9. SpringBoot 下 Mybatis 的缓存
  10. 关于python map代码理解实例
  11. 智能优化算法:蛇优化算法-附代码
  12. 基于netty,hessian的RPC框架
  13. paip.powerdesign cdm pdm文件 代码生成器 java web 页面 实现
  14. 少儿编程Scratch3.0初识
  15. Tippy.js - 免费开源且高度可定制的气泡提示独立组件
  16. excel中折线图怎样设置成箭头处没刻度线?
  17. Linux 下屏幕旋转
  18. 入门神经网络优化算法(六):二阶优化算法K-FAC
  19. GEE引擎架设好之后进游戏时白屏的解决方法——gee引擎白屏修复
  20. Pytorch版本代码修正

热门文章

  1. “非主流”数据库合集,简介
  2. 告别“浮云” 享用云计算服务优势
  3. 基于JAVA心灵治愈服务平台计算机毕业设计源码+系统+数据库+lw文档+部署
  4. Echo,Linux上最忧伤的命令(故事)
  5. Java底层小开发的面试经历
  6. 大家都在努力,你凭什么不努力
  7. java 大数加减算法
  8. JAVA-三种注释方式
  9. IP解析成地址 确定省市
  10. 小知识·adb安装和使用方法