欢迎关注 二师兄Kotlin
转载请注明出处 二师兄kotlin
友元对象扩展
如果一个类中定义了一个友元对象(companion object
),你就可以对这个友元对象进行函数和属性扩展。
class MyClass {
companion object { } // will be called "Companion"
}
fun MyClass.Companion.foo() {
// ...
}
正如友元对象的常规函数一样,只能使用所在类的类名作为前缀进行调用:
MyClass.foo()
扩展之作用域
很多情况下我们都在顶级包下进行扩展
package foo.bar
fun Baz.goo() { ... }
如果需要在超出包的范围内进行使用的话,需要进行导入(import):
package com.example.usage
import foo.bar.goo // importing all extensions by name "goo"
// or
import foo.bar.* // importing everything from "foo.bar"
fun usage(baz: Baz) {
baz.goo()
)
声明扩展作为成员函数
在一个类的内部,你可以为另外一个类声明扩展。而在扩展内部,则存在多个隐式的接收者---对象可以访问成员而不需显示指定归属类名。在声明扩展所在的类实例叫做分发接收者(dispatch receiver
),而扩展函数的接收者类的实例叫做扩展接收者( extension receiver
)。
class D {
fun bar() { ... }
}
class C {
fun baz() { ... }
fun D.foo() {
bar() // calls D.bar
baz() // calls C.baz
}
fun caller(d: D) {
d.foo() // call the extension function
}
}
万一 分发接收者和扩展接收者的函数名存在冲突,优先使用扩展接收者的函数。如果要引用分发接收者(dispatch receiver)的成员,请使用qualified this
syntax。
class C {
fun D.foo() {
toString() // calls D.toString()
this@C.toString() // calls C.toString()
}
将扩展函数声明时,可以使用open
来声明, 并且可以在子类中重写。这就意味着扩展函数对于分发接收者来说是虚函数,而对于扩展接收者来说是静态的。
open class D {
}
class D1 : D() {
}
open class C {
open fun D.foo() {
println("D.foo in C")
}
open fun D1.foo() {
println("D1.foo in C")
}
fun caller(d: D) {
d.foo() // call the extension function
}
}
class C1 : C() {
override fun D.foo() {
println("D.foo in C1")
}
override fun D1.foo() {
println("D1.foo in C1")
}
}
C().caller(D()) // prints "D.foo in C"
C1().caller(D()) // prints "D.foo in C1" - dispatch receiver is resolved virtually
C().caller(D1()) // prints "D.foo in C" - extension receiver is resolved statically
动机
在Java中,我们习惯于使用类名为*Utils
:FileUtils
, StringUtils
等等。著名的java.util.Collections
也属于这一类。但是这些类有一些用起来让人觉得很不爽的地方:
// Java
Collections.swap(list, Collections.binarySearch(list, Collections.max(otherList)),
Collections.max(list))
或者我们可以静态导入,变成这样写:
// Java
swap(list, binarySearch(list, max(otherList)), max(list))
虽然这样写会稍微好一些,但是我们却无法从IDE的强大的代码补全功能中获得帮助。如果我们可以这样写会不会更好一些呢:
// Java
list.swap(list.binarySearch(otherList.max()), list.max())
但是我们总不能实现List
的所有函数吧,这个时候Kotlin的扩展功能就可以对我们产生帮助了。
本节完