上节我们讲了Kotlin的函数式编程,本章我们来讲一下kotlin的扩展函数以及与Java不同的接口回调。
一、扩展函数的定义及原理
扩展函数其实就是相当于Java中的静态方法,这个静态方法的参数是接收者类型的对象,那么利用这个对象就可以访问这个类中的成员属性和方法了,并且最后会返回该对象本身,这样在外部感觉和使用类的成员函数是一样的,但和成员函数还是不同的,成员函数是真正的在该类内部,而扩展函数只不过是伪装为内部调用,也就无法访问类的成员属性和方法。
二、扩展函数的使用
只需要把扩展的类或者接口名称,放到即将要添加的函数名前面。这个类或者名称就叫做接收者类型,类的名称与函数之间用"."调用连接。this指代的就是接收者对象,它可以访问扩展的这个类可访问的方法和属性。
//创建一个data的类,data也是kotlin的关键字,内部帮我们实现了get,set方法
data class UserBean(var name:String,var age:Int)
//创建扩展函数
fun UserBean.print(){
println("姓名:$name 年龄:$age")
}
//调用
val user = UserBean("Bob",21)
user.print()
那既然有扩展函数,肯定也得有扩展属性,我们来看下怎么实现
data class UserBean(var name:String,var age:Int)
var UserBean.realName:String
get() = realName
set(newName) {
realName = newName
}
#################################################################
前边讲了扩展函数和扩展属性,下面我们来学一些Kotlin的接口回调和java有什么不同
在java中实现
//创建一个接口
public interface CallBackJava {
void print(String name,int age);
}
//创建业务逻辑层
public class Presser {
private CallBackJava callBack;
private void init() {
//todo
//接口回调
if (callBack != null) callBack.print("Bob", 21);
}
//设置callback
public void setCallBack(CallBackJava callBack) {
this.callBack = callBack;
}
}
//调用层调用
Presser presser = new Presser();
presser.setCallBack(new CallBackJava() {
@Override
public void print(String name, int age) {
System.out.println(name+age);
}
});
在kotlin中这样实现
interface CallBack {
fun print(name:String,age:Int)
}
class Presser {
private var callBack: CallBackJava? = null
private fun init() {
callBack?.print("Bob", 21)
}
fun setCallBack(callBack: CallBackJava?) {
this.callBack = callBack
}
}
//调用
val presser = Presser()
presser.setCallBack { name, age -> println("$name$age") }
what???这不是和java一样吗,也没显得多简洁啊,稍等我们可以这样优化,Kotlin不是可以将函数赋值给变量吗,我们省略创建接口,利用变量来代替,通过invoke调用,这样是不是更简洁了呢这也是利用了kotlin函数式编程特性的具体应用
class Presser {
private fun init() {
callBack.invoke("Bob", 21)
}
fun setCallBack(callBack: (name: String, age: Int) -> Unit) {
this.callBack = callBack
}
private lateinit var callBack: (name: String, age: Int) -> Unit
}
//调用
val presser = Presser()
presser.setCallBack { name, age ->
println("$name$age")
}
总结:当然,如果是接口中多个回调,就没办法用函数式改造了,如果整合成一个,通过定义type类型来操作也是可以。