【Kotlin】扩展函数作用域分析 ( 扩展函数导入 | 扩展函数重载 | 扩展函数作用域优先级 )
I . 扩展函数 作用域 总结
扩展函数作用域总结 :
① 扩展函数作用域 : 扩展函数使用需要导入包 , 如果在本包中使用 , 可以默认不导入包 ;
② 扩展函数可以重载 : 函数名相同 , 函数签名不同的扩展函数可以同时定义 , 导入包时导入一次即可调用所有的重载的扩展函数 ;
③ 扩展函数作用域优先级 : 声明导入的扩展函数优先级高于默认包的优先级 , 声明导入哪个包就调用哪个包的扩展函数 ;
II . 扩展函数 作用域
1 . 扩展函数作用域 : 定义一个扩展函数 , 默认只能在本包中调用 , 如果在别的包调用扩展函数 , 需要导入扩展函数 ;
2 . 扩展函数导入 : 调用接收者类型的扩展函数 , 需要导入扩展函数的包 , 导入格式为 :
import 包名.扩展函数名
- 1
3 . 调用定义在本包里的扩展函数 : 可以直接调用 , 导入扩展函数的操作可以省略 , 写上也不会出错 ;
4 . 调用定义在其它包的扩展函数 : 必须导入扩展函数 , 才能调用该扩展函数 ;
III . 扩展函数 作用域 简单调用示例
1 . 分别在 本包 和 外包 中定义扩展函数 :
① 本包定义扩展函数 : 普通的扩展函数定义 , 在 extendbean 包的文件下定义 Student 类 , 在 extendbean 包的文件下定义 Student 类的扩展函数 ;
package extendbean
class Student {
var name : String = "Tom"
var age : Int = 18
}
//在同一个文件中扩展
fun Student.printName(){
println("${this.name}")
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
② 外包定义扩展函数 : 外包中定义 Student 类的扩展函数 , 自然需要导入 Student 类 ;
package extenddeclare
import extendbean.Student
//定义扩展函数
fun Student.printNameAndAge(){
println("${this.name} , ${this.age}")
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
2 . 本包 中调用扩展函数 :
① 代码分析 : 在 extendbean 包中调用 extenddeclare 包中的为 Student 扩展的 printNameAndAge 函数 , 需要使用 import extenddeclare.printNameAndAge 导入该扩展函数 ;
package extendbean
//本包中可以不同导入 Student 包
//import extendbean.Student
//在本包内定义的扩展函数就不需要导入包了
//import extendbean.printAge
//import extendbean.printName
//使用 Student 的扩展 , 也需要导入 扩展函数所在包名.扩展函数名
import extenddeclare.printNameAndAge
fun main() {
var student : Student = Student()
student.printNameAndAge()
student.printName()
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
② 执行结果 :
Tom , 18
Tom
- 1
- 2
3 . 外包 中调用扩展函数 :
① 代码分析 : 在 extendusage 包中调用 extendbean 包中的 Student 类 和 扩展函数 , 以及 extenddeclare 包中定义的 printNameAndAge 扩展函数 , 需要将 Student 类以及所有的扩展函数都声明导入 , 才可以使用 ;
package extendusage
//使用到 Student 需要导入该类的包
import extendbean.Student
//使用 Student 的扩展 , 也需要导入 扩展函数所在包名.扩展函数名
import extendbean.printName
import extenddeclare.printNameAndAge
fun main() {
var student : Student = Student()
student.printNameAndAge()
student.printName()
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
② 执行结果 :
Tom , 18
Tom
- 1
- 2
IV . 扩展函数 重载分析
1 . 包内禁止定义相同函数签名的扩展函数 : 在同一个包里 , 定义了一个扩展函数后 , 不允许定义相同函数签名的扩展函数 ; 不管是定义在同一个文件中 , 还是不同的文件中 , 函数签名不可以重复 ;
2 . 原理分析 : 因为扩展函数是根据 包名.扩展函数名 识别的 , 如果在同一个包内定义了相同函数签名的扩展函数 , 无法识别应该调用哪个扩展函数 ;
3 . 重载说明 : 扩展函数在同一个包内 , 可以进行重载操作 , 即定义函数名相同 , 参数列表和返回值类型或顺序不同的函数 , 两个同名函数签名不同 , 因此可以区分调用 ;
V . 扩展函数 重载代码示例
1 . 重载扩展函数导入 : 对于重载的扩展函数 , 可以导入一次包即可通过函数签名调用不同的扩展函数 ;
2 . 定义重载扩展函数 : 为 Student 扩展了两个函数 , 分别是 printName() 和 printName(num : Int) , 这两个函数签名不同 , 可以定义 , 调用时根据不同的函数签名分别调用 ;
package extendbean
class Student {
var name : String = "Tom"
var age : Int = 18
}
//在同一个文件中扩展
fun Student.printName(){
println("${this.name}")
}
//测试重载的函数可以只声明一次
fun Student.printName(num : Int){
println("${this.name}")
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
3 . 调用重载扩展函数 : 根据不同的函数签名调用不同的扩展函数 ;
package extendbean
fun main() {
var student : Student = Student()
student.printName()
student.printName(10)
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
4 . 执行结果 :
Tom
name : Tom , num : 10
- 1
- 2
VI . 扩展函数 作用域 优先级 分析
本节讨论的是在不同包定义的相同函数签名的扩展函数调用问题
1 . 不同的包可以定义相同函数签名的扩展函数 : 在不同的包内 , 可以定义相同函数签名的扩展函数 , 调用时需要考虑各种情况 ; 其导入包的扩展函数优先级较高 , 没有发现导入包 , 才会去默认的本包中查找是否有定义该签名的扩展函数 ;
2 . 情况 一 : 在包内调用本包和外包的 相同签名的 扩展函数 ;
① 导入的包优先级高 : 如果导入外包扩展函数 , 就会调用外包的扩展函数 ;
② 本包默认优先级较低 : 如果没有导入 , 就会默认调用本包定义的的扩展函数 ;
3 . 情况 二 : 在一个包中调用 其它两个包 的 相同签名的 扩展函数 ;
① 调用优先级 : 导入哪个包 , 就调用哪个包的扩展函数 ;
② 重复导入 : 两个包都导入会报错 ;
VII . 扩展函数 作用域 优先级 代码示例分析
1 . 不同包中定义相同函数签名的扩展函数 : 为 Student 类在不同的包中定义相同函数签名的扩展函数 ;
① 在 extendbean 包定义了 Student.printNameAndAge() 扩展函数 :
package extendbean
class Student {
var name : String = "Tom"
var age : Int = 18
}
//定义扩展函数
fun Student.printNameAndAge(){
println("${this.name} , ${this.age}")
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
② 在 extenddeclare 包也定义了相同函数签名的 Student.printNameAndAge() 扩展函数 :
package extenddeclare
import extendbean.Student
//定义扩展函数
fun Student.printNameAndAge(){
println("${this.name} , ${this.age}")
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
2 . 在 extendbean 包中调用扩展函数分析 :
① 没有导入 extenddeclare.printNameAndAge 包 : 直接根据函数签名调用扩展函数 , 此时调用的是本包中定义的扩展函数 ;
package extendbean
//使用 Student 的扩展 , 也需要导入 扩展函数所在包名.扩展函数名
//import extenddeclare.printNameAndAge
//此处注释掉了导入包的操作
fun main() {
var student : Student = Student()
student.printNameAndAge()
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
执行结果 : 根据结果可以看到 , 调用的是 extendbean 包中的扩展函数 ;
extendbean : Tom , 18
- 1
② 导入了 extenddeclare.printNameAndAge 包 :
package extendbean
//使用 Student 的扩展 , 也需要导入 扩展函数所在包名.扩展函数名
import extenddeclare.printNameAndAge
fun main() {
var student : Student = Student()
student.printNameAndAge()
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
执行结果 : 根据结果可以看到 , 调用的是 extenddeclare 包中的扩展函数 ;
extenddeclare : Tom , 18
- 1
2 . 在 extendusage 包中调用扩展函数分析 : 这是个第三方包 , 分别在 extendbean 和 extenddeclare 定义了两个相同函数签名的 Student 扩展函数 ;
① 声明哪个包就调用对应包的方法 : 此时声明导入的是 extendbean.printNameAndAge , 就会调用 extendbean 包下的扩展函数 ;
package extendusage
//使用到 Student 需要导入该类的包
import extendbean.Student
import extendbean.printNameAndAge
//import extenddeclare.printNameAndAge
fun main() {
var student : Student = Student()
student.printNameAndAge()
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
执行结果 :
extendbean : Tom , 18
- 1
② 如果都声明报错 : 如果两个包都声明 , 会如下错误 Overload resolution ambiguity. All these functions match.
;
文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。
原文链接:hanshuliang.blog.csdn.net/article/details/105263661
- 点赞
- 收藏
- 关注作者
评论(0)