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

1、本文概要

本文是对<<Kotlin in Action>>的学习笔记,若是须要运行相应的代码能够访问在线环境 try.kotlinlang.org,这部分的思惟导图为: java

2、在 kotlin 中建立集合

kotlin中,建立HashSetArrayListHashMap的方法以下: 正则表达式

经过打印这些集合的类型,能够看到是采用的标准的 Java集合类:
这么作的缘由,是由于使用标准的 Java集合使 kotlin能够更容易地与 Java代码交互。当从 Kotlin调用 Java函数的时候,不用转换它的集合类来匹配 Java的类,反之亦然。

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

运行结果为:

3、让函数更好调用

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

运行结果为:

3.1 命名参数

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

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

下面,咱们使用命名参数,并在不改变函数定义的状况下,改变传入参数的顺序,也能够获得和上面相同的运行结果: 学习

对于命名参数,有如下几点须要注意:ui

  • 若是在调用一个函数时,指明了一个参数的名称,那它以后的全部参数都要代表名称。
  • 当调用Java函数时,不能使用命名参数。

3.2 默认参数值

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

运行结果为:
可是要注意:

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

3.3 顶层函数和属性

Java中,全部的代码都须要写做类的函数,可是在项目中,不少代码并不能归属到类中,这时候咱们通常会定义一个xxUtils类,并在其中声明static的静态方法。3d

kotlin中,咱们能够把这些函数直接放到代码文件的顶层,不用从属于任何的类,这些放在文件顶层的函数仍然是包内的成员,若是你须要从包外访问它,则须要import,但再也不须要额外包一层。code

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、扩展函数和属性

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

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

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、可变参数、中缀调用和库的支持

5.1 可变参数

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

运行结果为:
而若是咱们已经将参数打包成一个数组,这时候若是想要将它传递给一个接收可变参数的函数,那么须要先经过 *操做符进行解包:
运行结果为:

5.2 中缀调用

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

//通常函数调用。
1.to("One")
//中缀调用。
1 to "One"
复制代码

中缀调用能够与 只有一个参数的函数 一块儿使用,不管是普通的函数仍是扩展函数,要容许使用中缀符号调用函数,须要使用infix修饰符来标记它,下面是一个建立Person的函数,咱们采用了扩展函数的方法,这里的AnyKotlin中全部类的父类,和Java中的Object相同:

运行的结果为:

6、字符串处理

6.1 分割字符串

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

运行结果为:

6.2 正则表达式

假设有下面这个字符串

/Users/yole/kotlin-book/chapter.adoc
复制代码

咱们须要经过这个字符串获取到chapter.adoc的目录、文件名和扩展名,若是使用扩展函数,那么代码以下:

运行结果为:
下面是使用正则表达式的作法:
这个正则表达式将一个路径分为三个由斜线和点分隔的组:

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

7、局部函数

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

运行的结果为:


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

相关文章
相关标签/搜索