Kotlin 知识梳理(2) - 函数的定义与调用

Kotlin 知识梳理系列文章

Kotlin 知识梳理(1) - Kotlin 基础
Kotlin 知识梳理(2) - 函数的定义与调用
Kotlin 知识梳理(3) - 类、对象和接口
Kotlin 知识梳理(4) - 数据类、类委托 及 object 关键字
Kotlin 知识梳理(5) - lambda 表达式和成员引用
Kotlin 知识梳理(6) - Kotlin 的可空性
Kotlin 知识梳理(7) - Kotlin 的类型系统
Kotlin 知识梳理(8) - 运算符重载及其他约定
Kotlin 知识梳理(9) - 委托属性
Kotlin 知识梳理(10) - 高阶函数:Lambda 作为形参或返回值
Kotlin 知识梳理(11) - 内联函数
Kotlin 知识梳理(12) - 泛型类型参数


一、本文概要

本文是对<<Kotlin in Action>>的学习笔记,如果需要运行相应的代码可以访问在线环境 try.kotlinlang.org,这部分的思维导图为:

二、在 kotlin 中创建集合

kotlin中,创建HashSetArrayListHashMap的方法如下:


通过打印这些集合的类型,可以看到是采用的标准的Java集合类:

这么做的原因,是因为使用标准的Java集合使kotlin可以更容易地与Java代码交互。当从Kotlin调用Java函数的时候,不用转换它的集合类来匹配Java的类,反之亦然。

在这些集合对象上,我们除了可以使用Java当中定义的基本函数以外,还可以使用kotlin提供的扩展方法,例如下面的lastmax


运行结果为:

三、让函数更好调用

下面,我们定义一个函数,它的作用的是打印集合当中的元素,并指定元素之间添加分隔符、前缀和后缀:



运行结果为:


3.1 命名参数

在上面的例子中,我们指定了分隔符、前缀和后缀三个参数,但是对于这个函数的使用者来说,如果不去看这些函数的声明,很难看出这些String类型的含义,这时候就可以使用 命名参数 的方法来调用,这有两点好处:

  • 增加函数的可读性
  • 以想要的顺序指定需要的参数

下面,我们使用命名参数,并在不改变函数定义的情况下,改变传入参数的顺序,也可以得到和上面相同的运行结果:


对于命名参数,有以下几点需要注意:

  • 如果在调用一个函数时,指明了一个参数的名称,那它之后的所有参数都要表明名称。
  • 当调用Java函数时,不能使用命名参数。

3.2 默认参数值

kotlin中,可以在声明函数的时候,指定参数的默认值,这样就可以避免创建重载的函数,例如上面的例子,我们可以在 定义函数 时,指定三个String的默认值,而在 调用函数 的时候,如果没有传递这些参数,那么将会采用默认值:


运行结果为:

但是要注意:

  • 如果使用常规的调用语法时,必须按照函数声明中定义的参数顺序来给定参数,可以省略的只有排在末尾的参数。
  • 如果使用命名参数,可以省略中间的一些参数,也可以以你想要的任意顺序只给定你需要的参数,例如我们只修改前缀和后缀,分隔符仍然采用默认值:



    运行结果为:


3.3 顶层函数和属性

Java中,所有的代码都需要写作类的函数,但是在项目中,很多代码并不能归属到类中,这时候我们一般会定义一个xxUtils类,并在其中声明static的静态方法。

kotlin中,我们可以把这些函数直接放到代码文件的顶层,不用从属于任何的类,这些放在文件顶层的函数仍然是包内的成员,如果你需要从包外访问它,则需要import,但不再需要额外包一层。

3.3.1 在 Java 中调用顶层函数

如果我们想要在Java中调用这些顶层函数,则需要通过Kotlin根据包含函数的文件的名称生成的类,例如我们有两个文件

  • KotlinMethod.kt
fun kotlinFunc() {}
  • JavaCallKotlin.java
public class JavaCallKotlin {
    public JavaCallKotlin() {
        KotlinMethodKt.kotlinFunc();
    }
}

前者包含一个顶层函数,那么在Java中,就会根据该文件名生成一个{文件名}Kt的类型,再通过这个类来调用这个顶层函数。

如果不想使用默认的类名,可以在.kt文件的开头加上@file:JvmName("类名")的注解。

3.3.2 在 Java 中调用顶层属性

和函数一样,属性也可以放到文件的顶层。默认情况下,顶层属性和其他任意的属性一样,是通过访问器暴露给Java使用的(如果是val就只有一个getter,如果是var就对应gettersetter)。如果想要把一个常量以public static final的属性暴露给Java,可以使用const来修饰它。

package com.demo.lizejun.kotlinsample.chapter1

//不可变。
val kotlinVal = "kotlinValue"
//可变。
var kotlinVar = "kotlinVariable"
//常量。
const val kotlinConst = "kotlinConst"
//顶层函数。
fun kotlinFunc() {}

Java中,分别通过以下几种方式来访问或者修改这几个顶层属性:

package com.demo.lizejun.kotlinsample.chapter3;

import com.demo.lizejun.kotlinsample.chapter1.KotlinMethodKt;

public class JavaCallKotlin {
    public JavaCallKotlin() {
        KotlinMethodKt.kotlinFunc();
        //不可变。
        KotlinMethodKt.getKotlinVal();
        //可变。
        KotlinMethodKt.setKotlinVar("newKotlinVar");
        KotlinMethodKt.getKotlinVar();
        //常量。
        String kotlinConst = KotlinMethodKt.kotlinConst;
    }
}

四、扩展函数和属性

扩展函数 其实是一个类的成员函数,只不过它定义在类的外面,我们所需要做的,就是在声明扩展函数的时候,把需要扩展的类或者接口的名称,放到它的前面,用来调用这个扩展函数的对象,就叫做 接收者对象

在扩展函数中,可以直接访问被扩展的类的其它方法和属性,就好像是在这个类自己的方法中访问它们的一样,但是扩展函数不允许你打破它的封装性,扩展函数不能访问私有的或者是受保护的成员。

4.1 扩展函数的定义和使用

下面我们给String类添加一个扩展函数,返回它的最后一个字符:


运行结果为:

4.2 在 Java 中使用扩展函数

如果需要在Java中调用扩展函数,那么把接收者对象作为第一个参数传进去即可:

//接收者对象作为第一个参数。
char lastChar = KotlinMethodKt.last("Kotlin");

4.3 不能重写的扩展函数

这里假设我们有两个类,ViewButton,其中Button继承于View,我们给这两个类都添加一个名为showOff的扩展函数。


运行结果为:

尽管实际上这个变量是一个Button的对象,但是Kotlin会把扩展函数当做静态函数来对待,因此 扩展函数不存在重写

4.4 扩展属性

扩展属性提供了一种方法,用来扩展类的API,可以用来访问属性,用的是属性语法而不是函数的语法,尽管他们被称为属性,但它们没有任何状态,因为没有合适的地方来存储它们。

现在,我们给StringBuilder添加一个可读写的属性lastChar,用于获取或者改变它的最后一个字符,包含以下几点要素:

  • 扩展属性以var/val关键字开头
  • 指定扩展属性的名字、类型
  • 如果是var那么提供get()/set(value : T)方法,而如果是val属性,那么提供get()方法,其中T为属性的类型。

运行结果为:


五、可变参数、中缀调用和库的支持

5.1 可变参数

使用关键字 vararg,可以用来声明一个函数将有可能有任意数量的参数,下面例子中,我们定义一个可以接收可变数量Int类型的函数,之后和在Java中一样,它会被转换为[I的整型数组类型:


运行结果为:

而如果我们已经将参数打包成一个数组,这时候如果想要将它传递给一个接收可变参数的函数,那么需要先通过*操作符进行解包:

运行结果为:

5.2 中缀调用

中缀调用 不是特殊的内置结构,而是一种特殊的函数调用。在中缀调用中,没有添加额外的分隔符,函数名称是直接放在目标对象名称和参数之间。例如我们声明了一个to函数。

//一般函数调用。
1.to("One")
//中缀调用。
1 to "One"

中缀调用可以与 只有一个参数的函数 一起使用,无论是普通的函数还是扩展函数,要允许使用中缀符号调用函数,需要使用infix修饰符来标记它,下面是一个创建Person的函数,我们采用了扩展函数的方法,这里的AnyKotlin中所有类的父类,和Java中的Object相同:


运行的结果为:

六、字符串处理

6.1 分割字符串

Java中,我们会使用split来分割字符串,它接受一个正则表达式作为参数。但是当我们想分割"."时,会得到一个空的数组,因为.号表示任何字符的正则表达式。
而在kotlin中,它提供了一个接受Regex类型的重载函数,这样确保了当有一个字符串传递给这些函数的时候,不会被当做正则表达式,我们可以使用扩展函数toRegex将字符串转换为正则表达式。


运行结果为:

6.2 正则表达式

假设有下面这个字符串

/Users/yole/kotlin-book/chapter.adoc

我们需要通过这个字符串获取到chapter.adoc的目录、文件名和扩展名,如果使用扩展函数,那么代码如下:


运行结果为:

下面是使用正则表达式的做法:

这个正则表达式将一个路径分为三个由斜线和点分隔的组:

  • .模式从字符串的一开始就进行匹配,所以第一组(.+)包含最后一个斜线之前的子串,这和子串包含所有前面的斜线,因为它们匹配”任何字符“的模式。
  • 第二组包含最后一个点之前的子串
  • 第三组包含剩余部分

七、局部函数

Java的一个函数当中,有可能存在重复代码,例如在注册模块中,可能需要校验输入的多个字段是否有效,那么校验的逻辑就可以提取出一个函数,而Kotlin就提供了一种方法:可以在函数中嵌套这些提取的函数,局部函数定义方式和普通函数是相同的。


运行的结果为:


更多文章,欢迎访问我的 Android 知识梳理系列:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容