'by'关键字在Kotlin中做了什么?在为android开发时,我有时会遇到类似这样的东西:
var someModel: someViewModel by notNullAndObservable { vm ->
...
}
Run Code Online (Sandbox Code Playgroud)
我不明白'by'关键字的重要性是什么.
Jay*_*ard 50
在Kotlin参考中,您将找到两种用途by
,第一种是委托属性,这是您在上面使用的:
有一些常见的属性,虽然我们可以在每次需要时手动实现它们,但是一劳永逸地实现并放入库中会非常好.示例包括延迟属性:仅在首次访问时才计算值,可观察属性:侦听器收到有关此属性更改的通知,将属性存储在映射中,而不是分别存储在单独的字段中.
在这里,您将getter/setter委托给另一个完成工作的类,并且可以包含公共代码.作为另一个示例,Kotlin的一些依赖注入器通过将getter委托给从依赖注入引擎管理的实例的注册表接收值来支持该模型.
和接口/类代表团是其他用途:
已证明委派模式是实现继承的一个很好的替代方案,Kotlin支持它本身需要零样板代码.Derived类可以从接口Base继承,并将其所有公共方法委托给指定的对象
在这里,您可以将接口委托给另一个实现,因此实现类只需要覆盖它想要更改的内容,而其余的方法则委托回更全面的实现.
一个现实的例子是Klutter Readonly/Immutable集合,它们实际上只是将特定的集合接口委托给另一个类,然后覆盖readonly实现中需要不同的任何东西.节省大量工作而不必手动委派所有其他方法.
这两个都被Kotlin语言参考所涵盖,从那里开始学习该语言的基本主题.
oiy*_*yio 35
语法是:
val/var <property name>: <Type> by <expression>.
Run Code Online (Sandbox Code Playgroud)
by 后面的表达式是委托
如果我们尝试访问属性p的值,换句话说,如果我们调用属性p 的get()方法,则调用Delegate实例的getValue()方法。
如果我们尝试设置属性p的值,换句话说,如果我们调用属性p 的set()方法,则调用Delegate实例的setValue()方法。
ale*_*nov 18
财产委托:
import kotlin.reflect.KProperty
class Delegate {
// for get() method, ref - a reference to the object from
// which property is read. prop - property
operator fun getValue(ref: Any?, prop: KProperty<*>) = "textA"
// for set() method, 'v' stores the assigned value
operator fun setValue(ref: Any?, prop: KProperty<*>, v: String) {
println("value = $v")
}
}
object SampleBy {
var s: String by Delegate() // delegation for property
@JvmStatic fun main(args: Array<String>) {
println(s)
s = "textB"
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
textA
value = textB
Run Code Online (Sandbox Code Playgroud)
班级委托:
interface BaseInterface {
val value: String
fun f()
}
class ClassA: BaseInterface {
override val value = "property from ClassA"
override fun f() { println("fun from ClassA") }
}
// The ClassB can implement the BaseInterface by delegating all public
// members from the ClassA.
class ClassB(classA: BaseInterface): BaseInterface by classA {}
object SampleBy {
@JvmStatic fun main(args: Array<String>) {
val classB = ClassB(ClassA())
println(classB.value)
classB.f()
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
property from ClassA
fun from ClassA
Run Code Online (Sandbox Code Playgroud)
参数委托:
// for val properties Map is used; for var MutableMap is used
class User(mapA: Map<String, Any?>, mapB: MutableMap<String, Any?>) {
val name: String by mapA
val age: Int by mapA
var address: String by mapB
var id: Long by mapB
}
object SampleBy {
@JvmStatic fun main(args: Array<String>) {
val user = User(mapOf("name" to "John", "age" to 30),
mutableMapOf("address" to "city, street", "id" to 5000L))
println("name: ${user.name}; age: ${user.age}; " +
"address: ${user.address}; id: ${user.id}")
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
name: John; age: 30; address: city, street; id: 5000
Run Code Online (Sandbox Code Playgroud)
dan*_*ela 11
简而言之,您可以按所提供的关键字来理解。
从财产消费者的角度来看,val是具有getter(get)的东西,而var是具有getter和setter(get,set)的东西。对于每个var属性,都有一个默认的get和set方法提供程序,我们无需明确指定。
但是,当使用by关键字时,您要说明此getter / getter&setter是在其他位置提供的(即,它已被委派),它是由后面的函数提供的。
因此,您无需使用此内置的get和set方法,而是将该工作委托给某些显式函数。
一个非常常见的示例是通过惰性来实现延迟加载特性。另外,如果您使用像Koin这样的依赖注入库,您将看到许多这样定义的属性:
var myRepository: MyRepository by inject() //inject is a function from Koin
Run Code Online (Sandbox Code Playgroud)
在类定义中,它遵循相同的原理,它定义了提供某些功能的位置,但它可以引用任何方法/属性集,而不仅仅是get和set。
class MyClass: SomeInterface by SomeImplementation, SomeOtherInterface
Run Code Online (Sandbox Code Playgroud)
这段代码说:我是MyClass类,并且提供SomeImplementation提供的接口SomeInterface的功能。我将自己实现SomeOtherInterface(这是隐式的,因此没有实现)
归档时间: |
|
查看次数: |
8306 次 |
最近记录: |