当前位置: 首页 > 知识库问答 >
问题:

在Kotlin中访问属性委托

元修然
2023-03-14
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
}

共有1个答案

蓬祺
2023-03-14

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

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,这将在关闭时关闭任何已注册的Closeables。为了简化实现,我将这个接口委托给一个简单的基于列表的实现。

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

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()
}
 类似资料:
  • Kotlin具有委托属性,这是一个非常好的特性。但我正在研究如何获取和设置这些值。假设我想得到委托的财产的价值。在get()方法中,如何访问该值? 这是我如何实施的一个例子: 我无法理解的主要问题是,我如何将值设置为委托类被分配到的实际属性。当我将“NEW”赋给属性< code>p时,如何将该值存储到变量< code>p中,或者使用get读取传递给< code>p的新值?我是不是错过了一些基本的东

  • 假设我有一个JPA实体,比如 现在,我知道对于联接表中的每一个条目,这些属性都不能为空。(事实上,数据库强制执行此操作。) 好吧,让我们使用建议的解决方案,并转换为使用委托。 这仍然不能编译,因为 此批注不适用于目标“带有委托的成员属性” 我如何解决这个问题?

  • 下面是我在gradle的留档https://docs.gradle.org/current/userguide/tutorial_using_tasks.html中发现的代码片段 在上面,hello是提供任务定义/操作的TaskProvider类型。对hello的第二个调用是扩展任务的行为。 这个委托使用看起来有点让我困惑。以下是困扰我的问题: 1) 在检查反编译的字节码时,我看到了任务。注册返回

  • 我有一个kts gradle构建脚本,其中使用了这个插件。 插件将属性设置为字符串并添加一些附加属性: 虽然version属性是一个字符串,但它确实公开了一些其他属性。这些是、、、和 总是失败: 未解决的参考:主要 有没有办法访问这些属性,或者我必须回到基于groovy的<code>gradle。构建buildscript?

  • 就我的理解而言,在Kotlin中委托实现的想法是为了避免出现类似于以下内容的代码: 相反,我们可以编写以下代码,该代码也应该执行相同的操作: 现在,我希望是一个可变变量,即我的代码如下所示: 因此,如果Id自己将每个抽象方法委托给,就像在第一个示例中一样,更改的值确实会更改方法的行为。但是,上面的代码编译成这段Java代码: 因此,显然,Kotlin编译器不只是使用字段,而是决定在创建时将其复制到

  • 问题内容: 是否可以在SASS中访问HTML属性值?我有一行代码说 哪里是一些jQuery东西的结果。我需要计算一些CSS。如何将其另存为SASS变量? 或者,是否可以计算某个父元素的子元素数量?说我有这段代码: (您可能已经猜到了,matches的值与列表项的数量匹配。)SASS可以对列表项进行计数并将该数字保存为变量吗? 任何想法将不胜感激。 问题答案: Sass只是CSS生成器。它实际上并没