近两年开始使用kotlin替代java来开发android项目,感觉还不错,空指针类的bug少了很多,代码也比以前要简洁;但kotlin的一些特殊语法只停留在使用阶段,很少去总结,被人问起,就只能凭印象说个大概,这次就来总结一下apply,let,run,with,run。
let
let函数是一个作用域函数,在作用域内可使用it访问对象的公共属性和方法,返回值由作用域内最后一行决定,返回值类型是Any;
let的inline+lambda结构
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
return block(this)
}
结构分析: let函数只有block作为参数传入,并在代码块内通过it代指该对象,返回值为代码块的最后一行;
var user: TextEntity? = null
user.let {
it?.text // 可通过it访问其公共属性和函数
println("hello let1")
}
user?.let {
it.text // 做非空判断,为空则不执行
println("hello let2")
}
val result = user?.let {
1// 最后一行作为返回值,值类型为Any
}
使用场景:
场景一:对一个对象做判空处理; 场景二:在let作用域内访问该对象的公共属性和方法;
run
run是一个作用域函数,作用域内可通过this(可简写忽略)访问其内部公共属性和方法,并将作用域最后一行作为返回值,返回值类型是Any;
run函数的inline+lambda结构
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
return block()
}
结构分析: run函数只接受一个lambda函数作为参数,以闭包的形式返回;
var user: TextEntity? = null
user.run {
this?.text = "hello word" // 可通过this访问其公共属性和方法
println("hello run1")
}
user?.run {
text = "hello word" // 做非空判断,为空则不执行
println("hello run2")
}
val result: Int? = user?.run {
1 // 最后一行做返回值,类型是Any
}
使用场景: 使用场景和apply类似,可用于实例的初始化,比如加载xml时的数据绑定;
apply
apply函数是一个作用域函数,作用域内使用this来访问其对象的公共属性和方法,且返回值类型是对象本身;
apply函数的inline+lambda结构
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
block()
return this
}
结构分析: apply的结构和run的很相似,唯一不同的是返回结果是传入对象本身;
var user: TextEntity? = null
user.apply {
this?.text = "hello word" // 可通过this访问其公共属性和方法
println("hello apply1")
}
user?.apply {
text = "hello word" // 做非空判断,为空则不执行
println("hello apply2")
}
val result: TextEntity? = user?.apply {
// 返回值为this(对象本身)
}
使用场景: apply一般用于对象初始化时,进行内部赋值,比如adapter初始化时设置各类触摸监听事件,或者 加载xml时,对View绑定事件和数据也会用到;
with
with函数和之前的函数都不一样,它必须将对象作为参数传递进去,作用域内可通过this访问其公共属性和方法,且作用域内代码一定会执行,并将作用域内最后一行作为返回值,返回值类型是Any(Unit的父类是Any);
with函数的inline+lambda结构
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
return receiver.block()
}
结构分析: with函数需要将对象作为函数的参数传入,在函数块内通过this代指该对象,返回是为代码块最后一行;
var user: TextEntity? = null
with(user){
this?.text = "hello word" // 可通过this访问其公共属性和方法
}
with(user){
println("hello with1") // 不管对象是否为空,作用域内都会执行
}
println("hello with2")
val result = with(user) {
1 // 作用域内最后一行作为返回值
}
使用场景: 适用于调用同一个类的多个方法时,可以省去类名重复;比如Recyclerview中onBinderViewHolder中,数据的属性映射到UI上;
also
also函数是作用域函数,作用域内可通过it访问其公共的属性和方法,返回值是对象本身;
also的inline+lambda结构
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
block(this)
return this
}
结构分析: also函数是以闭包的形式返回,返回传入对象本身;
var user: TextEntity? = null
user.also {
it?.text = "hello word" // 可通过it访问其内部公共属性和方法
println("hello also1")
}
user?.also {
it.text = "hello word" // 做非空判断,为空则不执行
println("hello also2")
}
val result = user?.also {
// 返回值为this(对象本身),返回值和apply效果一致
}
使用场景: 可用于对象初始化赋值,比如加载xml时,为View绑定数据;