gpt4 book ai didi

properties - 在 Kotlin 中访问属性委托(delegate)

转载 作者:IT老高 更新时间:2023-10-28 13:34:59 24 4
gpt4 key购买 nike

Kotlin 具有委托(delegate)属性,这是一个非常好的特性。但有时 get()set() 方法是不够的。假设我想懒惰地创建一个 Closeable 对象并稍后关闭它。以下是如何实现此类委托(delegate)属性的示例:

fun <T : Closeable> closeableLazy(initializer: () -> T) =
CloseableLazyVal(initializer)

class CloseableLazyVal<T : Closeable>(
private val initializer: () -> T
) : ReadOnlyProperty<Any?, T> {

private var value: T? = null

override fun get(thisRef: Any?, desc: PropertyMetadata): T {
if (value == null) {
value = initializer()
}
return value
}

fun close() {
value?.close()
}
}

这就是我想使用它的方式:

private val stream by closeableLazy { FileOutputStream("/path/to/file") }

fun writeBytes(bytes: ByteArray) {
stream.write(bytes)
}

override fun close() {
stream::delegate.close() // This line will not compile
}

不幸的是,这种方法不起作用,因为 Kotlin 似乎不允许直接访问属性委托(delegate)。有什么办法可以做我想做的事吗?或者是否有任何计划将此类功能添加到 Kotlin,因为它会是一个非常简洁的功能。

最佳答案

好的,所以我想出了以下解决方案:

fun <T : Closeable> closeableLazy(initializer: () -> T) =
CloseableLazyVal(initializer)

class CloseableLazyVal<T : Closeable>(
private val initializer: () -> T
) : ReadOnlyProperty<CloseableDelegateHost, T> {

private var value: T? = null

override fun get(thisRef: CloseableDelegateHost, desc: PropertyMetadata): T {
if (value == null) {
value = initializer()
thisRef.registerCloseable(value!!)
}
return value!!
}

}

interface CloseableDelegateHost : Closeable {
fun registerCloseable(prop : Closeable)
}

class ClosableDelegateHostImpl : CloseableDelegateHost {

val closeables = arrayListOf<Closeable>()

override fun registerCloseable(prop: Closeable) {
closeables.add(prop)
}

override fun close() = closeables.forEach { it.close() }
}

class Foo : CloseableDelegateHost by ClosableDelegateHostImpl() {
private val stream by closeableLazy { FileOutputStream("/path/to/file") }

fun writeBytes(bytes: ByteArray) {
stream.write(bytes)
}

}

注意,该属性的get 方法有一个参数thisRef。我要求它从 CloseableDelegateHost 继承,它会在关闭时关闭任何已注册的 Closeable。为了简化实现,我将此接口(interface)委托(delegate)给一个简单的基于列表的实现。

更新(从评论中复制):我意识到,您可以将委托(delegate)声明为单独的属性,然后将第二个属性委托(delegate)给它。这样您就可以轻松访问委托(delegate)本身。

private val streamDelegate = closeableLazy { FileOutputStream("/path/to/file") }
private val stream by streamDelegate

fun writeBytes(bytes: ByteArray) {
stream.write(bytes)
}

override fun close() {
streamDelegate.close()
}

关于properties - 在 Kotlin 中访问属性委托(delegate),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30896314/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com