接口是用于实现多态编程的重要组成部分。我们知道,Java是单继承结构的语言,任何一个类最多只能继承一个父类,但是却可以实现任意多个接口,Kotlin也是如此。
Kotlin中定义接口的关键字和Java中是相同的,都是使用的 interface
而Kotlin中实现接口的关键字变量了冒号,和继承使用的是同样的关键字冒号,中间用逗号进行分隔:
熟悉Java的人都知道,Java中有public、private,protected和default(什么都不用写)这4种函数可见性修饰符。Kotlin中也有4种,分别是public、private 、protected和internal,需要使用哪种修饰符时,直接定义在 fun 关键字的前面即可。如下图(图取自第三行代码 3版):
数据类用于将服务器端或数据库中的数据映射到内存中,为编程逻辑提供数据模型的支持。或许你听过MVC,MVP,MVVM之类的架构模式,其中的M指的就是数据类。
Kotlin中使用data关键字可以定义一个数据类:
Kotlin会根据数据类的主构造函数中的参数将equals()、hashCode()、toString()等固定且无实际逻辑意义的方法自动生成,从而大大简少了开发的工作量。
单例模式可以用于避免创建重复的对象。
Kotlin中使用object关键字可以定义一个单例类:
而调用单例类中的函数比较类似于Java中静态方法的调用方式:Singleton.singletonTest()
这种写法虽然看上去像是静态方法的调用,但其实Kotlin在背后自动帮我们创建了一个Singleton类的实例,并且保证全局只会存在一个Singleton实例。
使用如下代码可以初始化一个List集合:
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape")
不过需要注意的是,listOf()函数创建的是一个不可变的集合。不可变的集合指的就是该集合只能用于读取,我们无法对集合进 行添加、修改或删除操作。
创建一个可变的集合:
使用如下代码可以初始化一个Set集合:
val set = setOf("Apple", "Banana", "Orange", "Pear", "Grape")
使用如下代码可以初始化一个Map集合:
val map = mapOf("Apple" to 1, "Banana" to 2, "Orange" to 3, "Pear" to 4, "Grape" to 5)
Lambda就是一小段可以作为参数传递的代码。正常情况下,我们向某个函数传参时只能传入变量,而借助Lambda却允许传入一小段代码。
我们来看一下Lambda表达式的语法结构:
{参数名1: 参数类型, 参数名2: 参数类型 -> 函数体}
首先最外层是一对大括号,如果有参数传入到Lambda表达式中的话,我们还需要声明参数列表,参数列表的结尾使用一个->符号,表示参数列表的结束以及函数体的开始,函数体中可以编写任意行代码,并且最后一行代码会自动作为Lambda表达式的返回值。
集合中的map函数是最常用的一种函数式API,它用于将集合中的每个元素都映射成一个另外的值,映射的规则在Lambda表达式中指定,最终生成一个新的集合。比如,这里我们希望让所有的水果名都变成大写模式,就可以这样写:
空指针是一种不受编程语言检查的运行时异常,只能由程序员主动通过逻辑判断来避免,但即使是最出色的程序员,也不可能将所有潜在的空指针异常全部考虑到。
Kotlin默认所有的参数和变量都不可为空,Kotlin提供了另外一套可为空的类型系统,就是在类名的后面加上一个问号。比如,Int表示不可为空的整型,而Int?就表示可为空的整型;String表示不可为空的字符串,而String?就表示可为空的字符串。
判空辅助工具:
?. 操作符表示当对象不为空时正常调用相应的方法,当对象为空时则什么都不做:
?: 操作符表示如果左边表达式的结果不为空就返回左边表达式的结果,否则就返回右边表达式的结果。比如:
val c = if (a ! = null) {
a } else { b }
这段代码的逻辑使用?:操作符就可以简化成:
val c = a ?: b
结合使用?.操作符和let函数也可以对多次重复调用的某个变量统一进行判空
fun doStudy(study: Study?) {
study?.let {
it.readBooks()
it.doHomework()
}
}