大家好,我是青空。今天给大家带来的是kotlin扩展。
文末可领取大厂面试题
Kotlin 扩展
定义
Kotlin 能够扩展一个类的新功能而无需继承该类或者使用像装饰者这样的设计模式。
比如说
-
为第三方库中无法修改的类编写 新function,新function就如同该类原来就存在的函数一般使用。
-
也可以为第三方类扩展一些新的属性
扩展函数
可以在已有类中添加新的方法,不会对原类做修改
fun receiverType.functionName(params){
body
}
receiverType
- 表示函数的接收者,也就是函数扩展的对象
functionName
- 扩展函数的名称
params
- 扩展函数的参数,可以为NULL
范例
class User(var name:String)
/**扩展函数**/
fun User.Print(){
print("用户名 $name")
}
fun main(arg:Array<String>){
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<String>){
printFoo(D()) //#输出c
}
若扩展函数和成员函数一致
- 优先使用成员函数
class C {
fun foo() { println("成员函数") }
}
fun C.foo() { println("扩展函数") }
fun main(arg:Array<String>){
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 <T> List<T>.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<String>) {
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<String>.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
}
最近又赶上跳槽的高峰期,好多粉丝,都问我有没有最新大厂面试题,我连日加班好多天,终于整理好了,1000+ 道,20多份大厂面试题大全,我会持续更新中!公众号回复【面试题】即可获取。