类委托
当一个类继承于另一个类或者实现某个接口,我们需要在该类中重写或者实现对应的方法,为了代码简练或者其他原因我们会用到委托
的思想,也就是让别的类来帮助我们完成这些事情,在Kotlin中对委托进行了原生的支持,用by
关键字实现。
//将Collection的方法委托给c对象完成
class DelegateCollection(val c: Collection) : Collection by c {}
属性委托
类里面的某个成员属性
也可以通过by
关键字进行委托实现,但实际上只是将该属性的选择器委托给了另外一个对象也就是getter/setter
,因此被委托者必须具有getValue/setValue
方法。
class Main{
val p by Delegate()
inner class Delegate {
operator fun getValue(): Any {
TODO()
}
}
}
懒加载
懒加载其实是一个非常实用的初始化方式,他会在被使用到的地方进行实例的初始化,把一些不用立刻使用的数据放到懒加载中可以提高页面整体的运行速度。通过by lazy
进行懒加载委托。
//这样就会在用到num的地方调用getNum方法,并将返回值赋给num
//这里其实是个lambda表达式,传过去的其实是个代码块,所以理论上可以通过任意形式返回任何对象,如方法,构造函数,代码块等等。
//并且默认情况下是线程安全的,如果需要可以设置使用哪个锁
val num by lazy{ getNum() }
最基本的反射功能是获取 Kotlin 类的运行时引用。要获取对静态已知的 Kotlin 类的引用,可以使用 类字面值 语法:
val c = MyClass::class
该引用是 KClass 类型的值。
请注意,Kotlin 类引用与 Java 类引用不同。要获得 Java 类引用, 请在 KClass 实例上使用 .java 属性。
val javaC = MyClass::class.java
除此之外还有一种:
val kProperty = MyClass::javaClass
public inline val <T : Any> T.javaClass: Class<T>
@Suppress("UsePropertyAccessSyntax")
get() = (this as java.lang.Object).getClass() as Class<T>
根据源码该引用获取的值应该等价于::class.java
,而实际上却是个kProperty类型,着实有点让人摸不着头脑。
函数、属性以及构造函数的引用,可以作为 lambda 函数直接被使用。
所有可调用引用的公共超类型是 KCallable, 其中 R 是返回值类型,对于属性是属性类型,对于构造函数是所构造类型。
fun isOdd(x: Int) = x % 2 != 0
可以通过引用的形式将其转换成 lambda 函数,让我们更加简单的对其进行调用。
val numbers = listOf(1, 2, 3)
numbers.filter(::isOdd)
这里 ::isOdd
是函数类型(Int) -> Boolean
的一个值。可以写成以下的形式:
val predicate: (Int) -> Boolean = ::isOdd
val numbers = listOf(1, 2, 3)
numbers.filter(predicate)
val x = 1
fun main() {
println(::x.get())
println(::x.name)
}
表达式 ::x 求值为 KProperty 类型的属性对象,它允许我们使用 get() 读取它的值,或者使用 name 属性来获取属性名。更多信息请参见关于 KProperty 类的文档。
用法:
val String.lastChar: Char
get() = this[length - 1]
fun main() {
println(String::lastChar.get("abc"))
}
在Java平台上,标准库包含反射类的扩展,它提供了与 Java 反射对象之间映射(参见 kotlin.reflect.jvm 包)。 例如,要查找一个用作 Kotlin 属性 getter 的 幕后字段或 Java方法,可以这样写:
import kotlin.reflect.jvm.*
class A(val p: Int)
fun main() {
println(A::p.javaGetter) // 输出 "public final int A.getP()"
println(A::p.javaField) // 输出 "private final int A.p"
}
构造函数可以像方法和属性那样引用。他们可以用于期待这样的函数类型对象的任何地方:它与该构造函数接受相同参数并且返回相应类型的对象。 通过使用 :: 操作符并添加类名来引用构造函数。考虑下面的函数, 它期待一个无参并返回 Foo 类型的函数参数:
class Foo
fun function(factory: () -> Foo) {
val x: Foo = factory()
}
fun main(){
function(::Foo)
}