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

静态编程语言中是否有didSet/will Set模拟?

汪典
2023-03-14

我喜欢这种Swift语法;它对很多事情都很有帮助:

var foo: Bar = Bar() {
    willSet {
        baz.prepareToDoTheThing()
    }
    didSet {
        baz.doTheThing()
    }
}

我很想在科特林做这件事。但是,我找不到合适的语法!

科特林有这样的事吗?

var foo: Bar = Bar()
    willSet() {
        baz.prepareToDoTheThing()
    }
    didSet() {
        baz.doTheThing()
    }

共有1个答案

羊煜
2023-03-14

尽管静态编程语言没有为属性更改观察提供内置的Swift风格的解决方案,但您仍然可以根据您的目标以多种方式进行。

>

  • 有一个可观察(…)委托(在stdlib中),允许您处理属性更改。使用示例:

    var foo: String by Delegates.observable("bar") { property, old, new ->
        println("$property has changed from $old to $new")
    }
    

    < sup >在这里,< code >“bar”是属性< code>foo的初始值,每次分配该属性后都会调用lambda,从而允许您观察变化。还有< code>vetoable(...)委托,该委托允许您阻止更改。

    可以使用属性的自定义 setter 在实际值更改之前/之后执行任意代码

    var foo: String = "foo"
        set(value: String) {
            baz.prepareToDoTheThing()
            field = value
            baz.doTheThing()
        }
    

    正如@KirillRakhman所指出的,此解决方案非常有效,因为它不会在方法调用和对象中引入任何开销,尽管在具有多个属性的情况下,代码会有点重复。

    通常,您可以实现自己的属性委托,在< code>getValue(...)和< code>setValue(...)函数。

    若要简化任务,请使用< code>ObservableProperty

    var foo: String by object : ObservableProperty<String>("bar") {
        override fun beforeChange(property: KProperty<*>, oldValue: String, newValue: String): Boolean {
            baz.prepareToDoTheThing()
            return true // return false if you don't want the change
        }
    
        override fun afterChange(property: KProperty<*>, oldValue: String, newValue: String) {
            baz.doTheThing()
        }
    }
    

    为了方便起见,您可以编写一个创建委托对象的函数:

    fun <T> observing(initialValue: T,
                      willSet: () -> Unit = { },
                      didSet: () -> Unit = { }
    ) = object : ObservableProperty<T>(initialValue) {
        override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean =
                true.apply { willSet() }
    
        override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = didSet()
     }
    

    然后,您只需将lambdas作为< code>willSet和< code>didSet传递给它(它们的默认参数是< code>{ })。用法:

    var foo: String by observing("bar", willSet = {
        baz.prepareToDoTheThing()
    }, didSet = {
        baz.doTheThing()
    })
    
    var baq: String by observing("bar", didSet = { println(baq) })
    

    在任何情况下,您都可以确保观察更改的代码不会再次设置该属性,因为它可能会陷入无限递归,或者您可以在观察代码中检查它是否以递归方式调用 setter。

  •  类似资料:
    • 我正在尝试使用柯特林 V1.2.70、Gradle V4.10.1 和 Java 11。使用 gradle 编译项目时,出现错误,指出“未知的 JVM 目标版本:11。支持的版本:1.6,1.8“。 Kotlin 编译器是否支持 Java 11(生成与 Java 11 JVM 兼容的代码)?如果是这样,如何使用渐变配置?

    • 我试图用OkHttp和Cucumber在静态编程语言中设置一个Spring启动项目,并且在运行Cucumber任务时遇到以下错误。如何修复? 还有build gradle kts片段 我看到了这个错误https://github.com/square/okio/issues/647看起来可能是它,并修复了这个build.gradle,我如何将其翻译为kotlinbuild.gradle.kts?

    • 我正在使用KotlinPoet和Auto Service自动生成代码。我没有找到任何方法来知道带注释的类是否具有“内部”修饰符,因此我可以使用相同的修饰符创建另一个类。例如: 所以我想使用静态编程语言反射我将能够得到这些信息,但没有运气。 关于如何做到这一点的任何线索?

    • 如图所示,https://stackoverflow.com/a/16639438/8949356,在Java中,当声明的类是公共类时,可以重写其函数 但是我想知道如何用静态编程语言编写完全相同的代码,我已经尝试了很多,但没有找到任何关于这个主题的东西。我可以在Java中去做这件事,但我的其余代码是用静态编程语言编写的,而且我不能一直带着这种怀疑;静态编程语言对我来说是一个很好的工具,我想学习它。

    • 问题内容: Swift具有类似于C#的属性声明语法: 但是,它也具有和动作。这些分别在设置器被调用之前和之后被调用。考虑到setter内可能只有相同的代码,它们的目的是什么? 问题答案: 重点似乎是有时您需要一个具有自动存储 和 某些行为的属性,例如,通知其他对象该属性刚刚更改。当您只有/时,您需要另一个字段来保存值。使用和,可以在修改值时采取措施,而无需其他字段。例如,在该示例中: 每次修改时都

    • 用Python我可以写: 如何用静态编程语言编写?