为了更动态的解决函数的扩展问题,进而提升编码效率。这算是一项程序员的福利。
除了文字版本,也有Xmind版本 github地址
目录结构是这样的
Kotlin 能够扩展一个类的新功能而无需继承该类或者使用像装饰者这样的设计模式。
可以在已有类中添加新的方法,不会对原类做修改
fun receiverType.functionName(params){
body
}
receiverType
表示函数的接收者,也就是函数扩展的对象
functionName
扩展函数的名称
params
扩展函数的参数,可以为NULL
class User(var name:String)
/**扩展函数**/
fun User.Print(){
print("用户名 $name")
}
fun main(arg:Array){
var user = User("Runoob")
user.Print()
}
是不是有一种js的既视感
具体被调用的的是哪一个函数
由调用函数的的对象表达式来决定
open class C
class D: C()
fun C.foo() = "c" // 扩展函数 foo
fun D.foo() = "d" // 扩展函数 foo
fun printFoo(c: C) {
println(c.foo()) // 类型是 C 类
}
fun main(arg:Array){
printFoo(D()) //#输出c
}
若扩展函数和成员函数一致
优先使用成员函数
class C {
fun foo() { println("成员函数") }
}
fun C.foo() { println("扩展函数") }
fun main(arg:Array){
var c = C()
c.foo() //#输出 成员函数
}
fun Any?.toMyString(): String {
if (this == null) return "null"
// 空检测之后,“this”会自动转换为非空类型,所以下面的 toString()
// 解析为 Any 类的成员函数
return toString()
}
这里的Any?是一个可以为null的对象;
通过 this == null的判断,可以让你在没有进行null判断,就调用toMyString方法
val List.lastIndex: Int
get() = size - 1
lastIndex是扩展出来的属性
只能通过get来获取
扩展属性只能被声明为 val
允许定义在类或者kotlin文件中
否则会报Local extension properties are not allowed
class Outer2 { // 外部类
private val bar: Int = 1
}
val Outer2.newBar : Int
get() = 222212
fun main(args: Array) {
println(Outer2().newBar) // 222212
}
因为是扩展的属性,他是不具备初始化器的。
val House.number = 1 // 错误:扩展属性不能有初始化器
class MyClass {
companion object { } // 将被称为 "Companion"
}
companion object即伴生对象
伴生对象在类中只能存在一个
类似于java中的静态方法
这可以这么写。
class MyClass {
companion object CcName{
} // 将被称为 "Companion"
}
fun MyClass.CcName.printCompanion() { println("companion") }
fun main() {
MyClass.CcName.printCompanion()
}
class MyClass {
companion object { } // 将被称为 "Companion"
}
fun MyClass.Companion.printCompanion() { println("companion") }
fun main() {
MyClass.printCompanion()
}
与java一样
需要import具体的,或者*
大多数时候我们在顶层定义扩展
package org.example.declarations
fun List.getLongestString() { /*……*/}
使用所定义包之外的一个扩展
package org.example.usage
import org.example.declarations.getLongestString
fun main() {
val list = listOf("red", "green", "blue")
list.getLongestString()
}
在一个类内部你可以为另一个类声明扩展
class Host(val hostname: String) {
fun printHostname() { print(hostname) }
}
class Connection(val host: Host, val port: Int) {
fun printPort() { print(port) }
fun Host.printConnectionString(p: Int) { //这是扩展函数。函数内的this指向Host本身。
//但是可以通过this指定到Connection的this
printHostname() // calls Host.printHostname()
print(":")
printPort() // calls Connection.printPort()
}
fun connect() {
/*……*/
host.printConnectionString(port) // calls the extension function
}
}
fun main() {
Connection(Host("kotl.in"), 443).connect()
//Host("kotl.in").printConnectionString(443) // error, the extension function is unavailable outside Connection
}
这个范例,kotlincn的说法其实是有点绕口的。细细品味,文中所谓的,不正说的是 this的指向问题吗?