带接收者的lambda: “with” 与 “apply”
所谓带接受者的lambda,就是在lambda中默认是带一个接受者对象的,而且并不需要显示调用,直接食用它的方法即可
with
with函数就是一个可以传入带接收者的lambda的函数
下面来看一个函数实现
fun alphabet() : String{
val result = StringBuilder()
for (letter in 'A'..'Z'){
result.append(letter)
}
result.append("\nNow I know the alphabet")
return result.toString()
}
这个函数中经常会用到result的函数,看起来重复,如果使用with函数实现就会简洁很多.
fun alphabet2():String{
val stringBuilder = StringBuilder()
return with(stringBuilder){ //接收者为stringBuilder
for (letter in 'A'..'Z'){
append(letter)
}
append("\nNow I know the alphabet")
toString()
}
}
上面函数中并没有重复的stringBuilder调用append和toString方法等,with函数中有两个参数一个是接受者对象,另外一个参数就是一个lambda表达式.
另外我们可以再次简化
fun alphabet() = with(StringBuilder()){
for(letter in ‘A’..’Z’){
append(letter)
}
append(“\nNow I know the alphabet!”)
toString()
}
方面名称冲突
有种情况lambda中表达式中接受者调用的方法和它外部类的方法名字一样,此时我想调用外部类的方法,英爱使用this@OuterClass.toString(), 实际操作如下
class Test{
override fun toString(): String {
println("my name is test")
return super.toString()
}
fun alphabet() = with(StringBuilder()){
for(letter in 'A'..'Z'){
append(letter)
}
append("\nNow I know the alphabet!")
this@Test.toString()
}
}
apply
apply函数和with函数几乎一样,唯一的区别是apply始终返回作为实参传递给它的对象(换句话说,接收者对象, 扩展函数的接收者对象就是调用函数对象本身)。
fun alphabet2() = StringBuilder().apply {
for (letter in 'A'..'Z'){
append(letter)
}
append("\nNow I know the alphabet! ")
}.toString()
apply还是一个很有用的函数,其中一种就是创建一个对象的实例并需要用正确的方式初始化它的一些属性的时候。按照以前的思路通常需要使用Builder对象来完成,
下面通过创建一个TextView使用apply初始化其中一些属性
fun createViewCustomAttributes(context : Context) = TextView(context).apply{
text = “Sample Text”
textSize = 20.0
setPadding(10,0,0,0)
}
在上面这段代码中TextView实例是apply函数的接收者,可以直接食用其中的属性进行初始化,最后apply默认返回调用者对象.
with和apply函数是最基本和最通用的使用带接受者的lambda例子.