扩展函数
在Kotlin中,可以对指定类进行扩展,通过扩展的特殊声明来实现。这里展示类中的函数扩展:
package com.xingen.kotlin.day2017527
fun main(args: Array<String>) {
Test().test()
}
/**
* 对函数进扩展:
* 在函数前面指定一个接受者,这里的接受者是MutabList<E>集合。
* 为它扩展一个swap函数
* 扩展函数的this指向接受者对象。
*
*/
fun <T> MutableList<T>.swap(x:Int,y:Int){
//利用一个中间变量,互换之指定位置的值。
val temp=this[x]
this[x]=this[y]
this[y]=temp
}
/**
* 使用中辍符号 infix来标记单个参数的扩展函数
*
* 好处,可以直接使用中辍注解来调用该扩展函数
*/
infix fun Int.diminished(x:Int):Int{
return x.dec() //数值自减
}
class Test {
fun test(){
/**
* 调用MutablListOf类的扩展方法swap( )
*/
var mutableList=mutableListOf("1",2,3)
println(mutableList)
//通过类对象来,使用自定义的扩展函数
mutableList.swap(0,2)
println(mutableList)
/**
* 调用Int类的扩展方法diminished()
*/
var normal=2
println(normal)
var instanceInt=1
println(instanceInt.diminished(normal))
//等同于 ,这里使用中缀符号的注解来调用函数 println( 1 diminished 2 )
}
}
输出结果:
[1, 2, 3]
[3, 2, 1]
2
1
可知:
- 对类中函数的扩展,即扩展函数,需要添加一个接受者,且函数中的this指针指向接受者。
infix
来标记单个参数的扩展函数,可以通过中辍注解来调用,函数中this指针指向接受者。
扩展函数注意点
扩展实际上并没有修改它所扩展的类。定义一个扩展,你并没有在类中插入一个新的成员,只是让对象.扩展函数()
的形式,来调用扩展函数。
package com.xingen.kotlin.day2017527
fun main(args: Array<String>) {
var instance =Test2017527()
//调用,父类和子类同名的扩展函数
printTest( instance)
//调用,类中与成员函数同名的扩展函数
instance.test1()
//调用,类中重载方式的同名扩展函数
instance.test1("Test2017527的重载方式实现同名的扩展函数")
// 调用,可空的接受者的扩展函数
var testInstance:Test2017527?=null
println( testInstance.toString() )
}
/**
* 通过对象来调用扩展函数
*/
fun printTest(t:BaseTest){
println( t.test() )
}
open class BaseTest{}
class Test2017527:BaseTest(){
fun test1(){
println("Test2017527的成员函数")
}
}
/**
* 父类和子类都定义同名的扩展函数
*/
fun BaseTest.test()="BaseTest.test()"
fun Test2017527.test() ="Test2017527.test()"
/**
* 定义类中的同名扩展方法
*/
fun Test2017527.test1(){
println("Test2017527的同名扩展函数")
}
/**
* 采用重载的方式,定义类中的同名扩展函数
*/
fun Test2017527.test1(str:String){
println(str)
}
/**
* 定义一个可空的接受者的扩展函数:空对象任然可以调用该扩展函数
*
* Any是超类,在toString()中检查是否为空的扩展函数。
* 这样实现,全部类(Any的子类)在不知道对象是否为空下,可以调用toString()来说生成字符串。
*/
fun Any?.toString():String{
if (this==null){ //空指针检查
return "对象为null"
} else{
return this.toString()
}
}
输出结果:
BaseTest.test()
Test2017527的成员函数
Test2017527的重载方式实现同名的扩展函数
对象为null
可知:
- 扩展函数是静态分发的,即扩展函数的调用是有发起函数调用的表达式的类型决定。简单来说,调用者的是什么类型,哪种表达式来决定的。
- 类中存在与成员函数同名的扩展函数,用方法名来调用的是成员函数
- 当类存在以重载方式实现的同名扩展函数,用方法名来调用的是扩展函数
- 扩展函数的接受者可以为空,即空对象任然可以调用该扩展函数。