开始
对一个对象实例调用多个方法(使用 with)
class Turtle {
fun penDown()
fun penUp()
fun turn(degrees: Double)
fun forward(pixels: Double)
}
val myTurtle = Turtle()
with(myTurtle) { // 画一个 100 像素的正方形
penDown()
for(i in 1..4) {
forward(100.0)
turn(90.0)
}
penUp()
}
配置对象的属性(使用 apply)
val myRectangle = Rectangle().apply {
length = 4
breadth = 5
color = 0xFAFAFA
}
类与对象
属性与字段
幕后字段
var counter = 0 // Note: the initializer assigns the backing field directly
set(value) {
if (value >= 0) field = value
}
用value
的值指定counter
的值。
幕后属性
private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
get() {
if (_table == null) {
_table = HashMap()
}
return _table ?: throw AssertionError("Set to null by another thread")
}
可见性修饰符
类、对象、接口、构造函数、方法、属性和它们的 setter 都可以有可见性修饰符(getter 与属性有相同的可见性)。
Kotlin 中有 private
protected
internal
public
四个可见性修饰符,默认是public
。
internal
模块内可见。
注意:Kotlin 中,外部类不能访问到内部类的private
成员。
对象声明
即一个关键字object
实现单例。
伴生对象
用companion
关键字声明伴生对象,即类内部的对象。
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
委托
interface Base {
fun print()
}
class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
}
class Derived(b: Base) : Base by b
fun main() {
val b = BaseImpl(10)
Derived(b).print()
}
可以看到Derived
类相比普通的声明多了by b
这部分,这部分的意思就是说把b
的公有成员都委托给Derived
。
委托属性
标准委托
Kotlin 标准库中内置了几种委托。
延迟属性 Lazy
lazy()
接受一个 lambda 并返回一个Lazy<T>
的实例,返回的实例作为延迟属性的委托。第一次调用 get()
会执行已传递给 lazy()
的 lambda 表达式并记录结果, 后续调用 get()
只返回记录的结果。
可观察属性 Observable
import kotlin.properties.Delegates
class User {
var name: String by Delegates.observable("<no name>") {
prop, old, new ->
println(prop)
println("$old -> $new")
}
}
fun main() {
val user = User()
user.name = "first"
user.name = "second"
}
Delegates.observable()
接受两个参数初始值inintalValue
和值改变时的回调方法onChange
,onChange
接受三个参数:被赋值的属性,旧值,新值。在回调方法被调用前,值已经改变过了。
如果需要拦截新值并否决,可以使用vetoable()
代替observable()
,在新值生效前会调用回调方法。
把属性储存在 map 中
class User(val map: Map<String, Any?>) {
val name: String by map
val age: Int by map
}
fun main() {
val user = User(mapOf(
"name" to "John Doe",
"age" to 25
))
println(user.name) // Prints "John Doe"
println(user.age) // Prints 25
}
函数
函数可以有默认参数。当覆盖(重写)一个有默认参数的函数时,新函数不可以设置默认值。
当向函数传递参数时,可以指定参数的名称。
函数的可变参数(通常是最后一个)可以用 vararg
修饰符标记。当把一个数组a
传给可变参数,可以用*a
(伸展操作符 Spread )。
中缀表示函数:
infix fun Int.shl(x: Int): Int { …… }
// 用中缀表示法调用该函数
1 shl 2
// 等同于这样
1.shl(2)
高阶函数和 Lambda 表达式
高阶函数是将函数用作参数或返回值的函数。
Kotlin 中,如果一个函数的参数的最后一个参数为函数,则这个函数参数可以放在()
外,写在{}
里。更甚,如只有一个参数且为函数,则()
也可省略。
Lambda 表达式或者匿名函数(以及局部函数和对象表达式) 可以访问其 闭包 ,即在外部作用域中声明的变量。 在 lambda 表达式中可以修改闭包中捕获的变量:
var sum = 0
ints.filter { it > 0 }.forEach {
sum += it
}
print(sum)
内联函数
inline
修饰符会影响函数本身和传给它的 lambda 表达式,它们被内联到调用处,可以提高一些效率。
inline fun <T> lock(lock: Lock, body: () -> T): T { …… }
lock(l) { foo() }
l.lock()
try {
foo()
}
finally {
l.unlock()
}
扩展函数
fun MutableList<Int>.swap(index1: Int, index2: Int) {
val tmp = this[index1]
this[index1] = this[index2]
this[index2] = tmp
}
val list = mutableListOf(1, 2, 3)
list.swap(0, 2)
作用域函数
函数 | 对象引用 | 返回值 | 是否是扩展函数 |
---|---|---|---|
let | it | Lambda 表达式结果 | 是 |
run | this | Lambda 表达式结果 | 是 |
run | - | Lambda 表达式结果 | 不是:调用无需上下文对象 |
with | this | Lambda 表达式结果 | 不是:把上下文对象当做参数 |
apply | this | 上下文对象 | 是 |
also | it | 上下文对象 | 是 |
协程
参考
待
2020-3-17 23:50:39