1. 构造函数
在 Kotlin 中的⼀个类可以有⼀个主构造函数和⼀个或多个次构造函数。主构造函数是类头的⼀部分:它跟在类名后。
class Person constructor(firstName: String) {
}
如果主构造函数没有任何注解或者可⻅性修饰符,可以省略这个 constructor 关键字。
class Person(firstName: String) {
}
主构造函数不能包含任何的代码,初始化的代码可以放到以 init 关键字作为前缀的初始化块(initializer blocks)中:
class Customer(name: String) {
init {
logger.info("Customer initialized with value ${name}")
}
}
注意,主构造的参数可以在初始化块中使⽤。它们也可以在类体内声明的属性初始化器中使⽤:
class Customer(name: String) {
val customerKey = name.toUpperCase()
}
与普通属性⼀样,主构造函数中声明的属性可以是可变的(var)或只读的(val)。
如果构造函数有注解或可⻅性修饰符,这个 constructor 关键字是必须的,并且这些修饰符在它前⾯:
class Customer public @Inject constructor(name: String) { …… }
类也可以声明前缀有 constructor的次构造函数:
class Person {
constructor(parent: Person) {
parent.children.add(this)
}
}
如果类有⼀个主构造函数,每个次构造函数需要委托给主构造函数, 可以直接委托或者通过别的次构造函数间接委托。委托到同⼀个类的另⼀个构造函数⽤ this 关键字即可:
class Person(val name: String) {
constructor(name: String, parent: Person) : this(name) {
parent.children.add(this)
}
}
如果⼀个⾮抽象类没有声明任何(主或次)构造函数,它会有⼀个⽣成的不带参数的主构造函数。构造函数的可⻅性是 public。如果你不希望你的类有⼀个公有构造函数,你需要声明⼀个带有⾮默认可⻅性的空的主构造函数:
class DontCreateMe private constructor () {
}
2. run、with、apply、also、let、takeIf、takeUnless
标题上的函数都位于 Standard.kt文件下,下面我们一个个过一遍:
- run
/**
* Calls the specified function [block] and returns its result.
*/
@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R = block()
在kotlin中,将函数⽤作参数或返回值的函数叫高阶函数。这里把block()
作为参数,其返回值和run
方法的返回值相同,为R
。举个栗子:
kotlin.run { findViewById<TextView>(R.id.text_view) }.text = "kotlin"
/**
* Calls the specified function [block] with `this` value as its receiver and returns its result.
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R = block()
这个run
方法为T
类的扩展方法(关于扩展方法不懂的自行百度),方法的返回值是block()
的返回值,这里注意block()
也是T
类的扩展方法。
举个栗子,run:
findViewById<TextView>(R.id.text_view).run {
text = "kotlin" //设置textview内容,返回值为Unit
}
- with
/**
* Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
with不是扩展方法,它的第一个参数是一个T类型的接收者,第二个参数为T的扩展方法block()
,返回值为block()
的返回值。看栗子:
with(findViewById<TextView>(R.id.text_view)){
text = "kotlin"
}
- apply
/**
* Calls the specified function [block] with `this` value as its receiver and returns `this` value.
*/
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
apply函数返回值为它本身,参数为T
的扩展方法,看栗子:
//f返回值为TextView
findViewById<TextView>(R.id.text_view).apply {
text = "kotlin" //设置textview内容
}.setOnClickListener { ... }
- also
/**
* Calls the specified function [block] with `this` value as its argument and returns `this` value.
*/
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this }
also函数是T类的扩展方法,返回值类型为T,参数为block(T)函数,block(T)函数的参数为T,无返回值:
//返回值为TextView
findViewById<TextView>(R.id.text_view).also {
it.text = "kotlin" //设置textview内容
}.setOnClickListener { ... }
- let
/**
* Calls the specified function [block] with `this` value as its argument and returns its result.
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
let函数是T类的扩展方法,返回值类型为block方法的返回值类型,block方法的参数为T:
findViewById<TextView>(R.id.text_view).let {
it.text = "kotlin"
}//返回值类型为setText的返回值类型
- takeIf
/**
* Returns `this` value if it satisfies the given [predicate] or `null`, if it doesn't.
*/
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? = if (predicate(this)) this else null
takeIf函数为T类扩展方法,参数为predicate()方法,这个方法的参数为T,返回值为Boolean,如果为true返回T,否则返回null:
findViewById<TextView>(R.id.text_view).takeIf {
it.text.isEmpty()
}?.text = "kotlin"//如果TextView的text不为空就会返回null,需要空安全
- takeUnless
/**
* Returns `this` value if it _does not_ satisfy the given [predicate] or `null`, if it does.
*/
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? = if (!predicate(this)) this else null
和 takeIf相反。