1、扩展函数
扩展函数表示即使在不修改某个类的源码的情况下,仍然可以打开这个类,向该类添加新的函数。
其语法结构非常简单,如下所示:
fun ClassName.methodName(param1: Int, param2: Int): Int {
return 0
}
我们先来看一个示例
定义一个lettersCount方法,用于统计字符串中包含字母的数量
fun lettersCount(str: String): Int {
var count = 0
for (char in str) {
if (char.isLetter()) {
count++
}
}
return count
}
然后是调用
val str = "ABC123xyz!@#"
val count =lettersCount(str)
接下来我们来试一下扩展函数的写法
只需在一个kotlin file 文件中添加以下函数
fun String.lettersCount(): Int {
var count = 0
for (char in this) {
if (char.isLetter()) {
count++
}
}
return count
}
我们就可以在其他地方使用扩展函数得使用了
val str = "ABC123xyz!@#"
str.lettersCount();
就和这个方法就是String的方法一样
2、扩展函数是静态解析的
扩展函数是静态解析的,并不是接收者类型的虚拟成员,在调用扩展函数时,具体被调用的的是哪一个函数,由调用函数的的对象表达式来决定的,而不是动态的类型决定的:
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<String>){
printFoo(D())
}
实例执行输出结果为:
c
若扩展函数和成员函数一致,则使用该函数时,会优先使用成员函数。
class C {
fun foo() { println("成员函数") }
}
fun C.foo() { println("扩展函数") }
fun main(arg:Array<String>){
var c = C()
c.foo()
}
实例执行输出结果为:
成员函数
3、扩展一个空对象
在扩展函数内, 可以通过 this 来判断接收者是否为 NULL,这样,即使接收者为 NULL,也可以调用扩展函数。例如:
fun Any?.toString(): String {
if (this == null) return "null"
// 空检测之后,“this”会自动转换为非空类型,所以下面的 toString()
// 解析为 Any 类的成员函数
return toString()
}
fun main(arg:Array<String>){
var t = null
println(t.toString())
}
实例执行输出结果为:
null
扩展属性
除了函数,Kotlin 也支持属性对属性进行扩展:
val <T> List<T>.lastIndex: Int
get() = size - 1
扩展属性允许定义在类或者kotlin文件中,不允许定义在函数中。初始化属性因为属性没有后端字段(backing field),所以不允许被初始化,只能由显式提供的 getter/setter 定义。
val Foo.bar = 1 // 错误:扩展属性不能有初始化器
扩展属性只能被声明为 val。
4、伴生对象的扩展
如果一个类定义有一个伴生对象 ,你也可以为伴生对象定义扩展函数和属性。
伴生对象通过"类名."形式调用伴生对象,伴生对象声明的扩展函数,通过用类名限定符来调用:
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()
}
实例执行输出结果为:
no:10
伴随对象的扩展函数
5、运算符重载
Kotlin的运算符重载允许我们让任意两个对象进行相加,或者是进行更多其他的运算操作。
这里以加号运算符为例,如果想要实现让两个对象相加的功能,那么它的语法结构如下:
class Obj {
operator fun plus(obj: Obj): Obj {
// 处理相加的逻辑
}
}
接下来我们来实现下来两个Money对象得相加
首先常见Money类
class Money(val value: Int)
接下来就重载Money得加法运算
class Money(val value: Int) {
operator fun plus(money: Money): Money {
val sum = value + money.value
return Money(sum)
}
}
那么我们就可以用
val money1 = Money(5)
val money2 = Money(10)
val money3 = money1 + money2
println(money3)
同时Kotlin允许我们对同一个运算符进行多重重载,我们再实现一个Money与整形数的加法
class Money(val value: Int) {
operator fun plus(money: Money): Money {
val sum = value + money.value
return Money(sum)
}
operator fun plus(newValue: Int): Money {
val sum = value + newValue
return Money(sum)
}
}
测试一下
val money1 = Money(5)
val money2 = Money(10)
val money3 = money1 + money2
val money4 = money3 + 20
println(money4)
参考自 第一行代码3,以及菜鸟教程