kotlin扩展

扩展函数,它可以在已有类中添加新方法,而不对原类做出修改。

1
2
3
fun receiverType.functionName(params){
body
}

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
class User(var name:String)
- receiverType:表示函数的接收者,也就是函数扩展的对象
- functionName:扩展函数的名称
- params:扩展函数的参数,可以为NULL
/**扩展函数**/
fun User.Print(){
print("用户名 $name")
}

fun main(arg:Array<String>){
var user = User("Runoob")
user.Print()
}

扩展函数是静态解析的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package top.zfxt
open class a{
open fun out(){
println("我是a的函数")
}
}
class b:a(){
override fun out(){
println("我是b的函数")

}
}
fun printout(a:a){
println(a.out())
}
//扩展函数
fun a.foo()="a"
fun b.foo()="b"
//写一个函数来判断扩展函数是否也满足动态绑定。
fun printfoo(a:a){
println(a.foo())
}
fun main() {
var user:a = b()
//第一个user表明,他任然是满足动态绑定的。可以实现java中所理解的动态绑定。
user.out()
//第二个函数中也与上一个一致
printout(b())
//第三个函数用来判断扩展函数是否满足动态绑定
printfoo(b())
}

结果展示

1
2
3
4
我是b的函数
我是b的函数
kotlin.Unit
a

如果函数没有继承,那么两个父子类他们都具有同名的函数,此时,会根据传递进去时要求的参数类型判断是执行什么函数。

若扩展函数和成员函数一致,则使用该函数时,会优先使用成员函数。

1
2
3
4
5
6
7
8
9
10
class C {
fun foo() { println("成员函数") }
}

fun C.foo() { println("扩展函数") }

fun main(arg:Array<String>){
var c = C()
c.foo()
}

同样的,kotlin也可以扩展属性,但是他扩展属性并不能初始化,只能通过修改他的get和set方法。

1
2
3
4
val <T> List<T>.lastIndex: Int
get() = size - 1
//正确,修改了lastIndex的属性方法。
val Foo.bar = 1 // 错误:扩展属性不能有初始化器

伴生对象

这个伴生对象可以理解为是静态属性和静态方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class MyClass {
companion object { } // 将被称为 "Companion"
}

fun MyClass.Companion.foo() {
println("伴随对象的扩展函数")
}

val MyClass.Companion.no: Int
get() = 10

fun main(args: Array<String>) {
println("no:${MyClass.no}")
MyClass.foo()
}
//或者直接在伴生对象中说明他的方法和属性都是被允许的
class Student{
companion object{
fun add(a:Int,b:Int) = a+b
}

}

当你在其他的包内使用该类的扩展属性或方法时,需要将他的本类和他的扩展方法都导入

1
2
3
package foo.bar

fun Baz.goo() { …… }

要使用所定义包之外的一个扩展, 通过import导入扩展的函数名进行使用:

1
2
3
4
5
6
7
8
9
package com.example.usage

import foo.bar.goo // 导入所有名为 goo 的扩展
// 或者
import foo.bar.* // 从 foo.bar 导入一切

fun usage(baz: Baz) {
baz.goo()
}

扩展声明为成员

在一个类内部你可以为另一个类声明扩展。

在这个扩展中,有个多个隐含的接受者,其中扩展方法定义所在类的实例称为分发接受者,而扩展方法的目标类型的实例称为扩展接受者。
假如在调用某一个函数,而该函数在分发接受者和扩展接受者均存在,则以扩展接收者优先,要引用分发接收者的成员你可以使用限定的 this 语法。