Kotlin系列(十一)扩展函数详解
- 更多分享:www.catbro.cn
一、前言:
- 扩展类的函数, 即 Extension Function , 可以在已有类中添加新的方法, 比继承更加简洁和优雅.
- 函数的扩展其实是一个非常实用的特性。
- 使用过Swift的小伙伴应该非常熟悉
二、概念
- 在Kotlin中,允许在不需要继承或使用 Decorator 模式情况下通过一种特殊形式的声明对类进行扩展,实现某一具体功能。
- 扩展函数是静态解析的,并未对原类增添函数或者属性,也就是说对其本身没有丝毫影响。
三、定义形式
1、扩展函数定义形式:
-
如果对一个类某一功能并不通用,只有某些特殊场景使用时,可以使用扩展函数,从而让变成灵活多变。
fun receiverType .functionName(params){ body }
-
函数解析:
- receiverType:表示函数的接收者,也就是函数扩展的对象
- functionName:扩展函数的名称
- params:扩展函数的参数,可以为NULL
-
扩展函数并没有对原类做修改,而是为被扩展类的对象添加新的函数。
-
示例代码如下:我们对Int类进行扩展
fun Int.sayHello(){ println("hello,I am anjie"); } @Test fun test12(){ var a :Int =1; a.sayHello(); }
-
运行结果为:hello,I am anjie
-
可以发现,我们在不影响系统Int类型的基础上对Int
2、扩展函数是静态解析的
-
Kotlin的扩展函数是静态解析的,并不是作为接收者类型的虚拟成员而存在。
-
静态解析也就意味着调用扩展函数时,具体被调用的的是哪一个函数,由调用函数的对象表达式来决定的,而不是动态的类型决定的。
-
例子:声明了两个类Person和Student,其中Student继承于Person。
-
示例代码如下
open class Person { } class Student : Person() { } fun Person.sayHello() { println("I am Person") } fun Student.sayHello() { println("I am Student") } fun sayGoodby(person: Person) { person.sayHello(); println("BoodBy") } @Test fun test13() { var student = Student(); var person = Person(); student.sayHello(); person.sayHello(); sayGoodby(student); }
-
运行结果如下:
I am Student I am Person I am Person BoodBy
-
代码解析:
-
1、我们分别对Person和Student声明扩展函数sayHello(),又声明了sayGoodby()方法,其参数是一个Person对象,在其方法体内,调用了Person的扩展函数。
-
在调用案例中,创建了一个Student对象student,调用student的扩展函数sayHello,打印了I am Student;创建一个Person对象person,调用扩展函数sayHello,打印了I am Person,说明扩展方法是跟着类走的。
-
最后我们调用sayGoodby方法,传入的student实例,注意了,我们的Student继承自Person,此时打印的sayHello仍然为Person的扩展方法。
-
从中我们能够得出一个结论,扩展函数的调用跟着对象类型走,而非实际对象实例。你可以认为是kotlin在编译时为扩展方法指定的类添加的静态方法。
3、类成员函数与类扩展函数函数相同问题
-
当类的成员函数与扩展函数一摸一样是,是调用扩展函数还是成员函数呢?
-
带着这样的疑问我们来实践一下
-
示例代码如下:
open class Person { fun sayHello(){ println("我是person类成员函数") } } class Student : Person() { } fun Person.sayHello() { println("I am Person") } fun Student.sayHello() { println("I am Student") } fun sayGoodby(person: Person) { person.sayHello(); println("BoodBy") } @Test fun test13() { var student = Student(); var person = Person(); student.sayHello(); person.sayHello(); sayGoodby(student); }
-
结果输出如下:
我是person类成员函数 我是person类成员函数 我是person类成员函数 BoodBy
- 可以看到,当类成员函数与方法成员函数一致时,调用的时类成员函数。
4、接收者可为NULL
-
在扩展函数内,我们可以通过this来判断接收者是否为NULL。
-
这样做的好处是什么呢?假如接收者为NULL,我们也可以通过判断做相对的处理。
fun Person.sayHello() { if (null == this) { println("null") } println("sayHello") }
三、扩展属性
-
扩展属性, 即 Extension Property , 即把某些函数添加为数据, 使用”=”, 直接设置或使用。
-
通过扩展属性,我们可以像添加扩展函数一样给类添加扩展属性,当然,扩展属性也是静态编译的。所以扩展属性实际上不会向类添加新的成员, 扩展属性的行为只能通过明确给定的取值方法与设值方法来定义。
-
扩展属性只能被声明为val而不能被声明为var.
-
示例代码如下:我们给Int类添加一个name属性,访问该属性直接返回Int对应的String形式的值
val Int.name:String get() = this.toString(); @Test fun test14() { var a: Int = 100; println(a.name) }
-
运行结果如下:100