【问题标题】:How to use kotlin functional programming to access a property如何使用 kotlin 函数式编程来访问属性
【发布时间】:2021-11-18 09:59:23
【问题描述】:

我目前有以下功能:

fun createMask(mask : String){
    val ssnField : mywidgets.SSNField = findViewById (R.id.editTextText)
    ssnField.hint = mask
}

为了对此进行单元测试,我想将 createMask 中不可测试的代码包装到一个闭包中。 (不可测试的代码是难以在单元测试中实例化和执行的视图层逻辑。)这是我想要在伪代码中做的事情:

createMask(closure, mask : String){
    closure = mask  // closure function returns pointer to property (depending on closure return type, might need to use setter: closure.set(mask))
}

使用上述内容,调用者会这样做:

fun caller(){
    createMask((){
        val ssnField : mywidgets.SSNField = findViewById (R.id.editTextText)
        return ssnField.hint
    }, "xxx-xx-xxx")
}

在 kotlin 中用伪代码表达的内容是如何工作的?

【问题讨论】:

    标签: unit-testing kotlin closures


    【解决方案1】:

    如果您使createMask 接受() -> KMutableProperty0<String> 类型的参数,您可以返回该属性的引用。然后就可以调用set方法了:

    fun createMask(mask : String, block: () -> KMutableProperty0<String>) {
        block().set(mask)
    }
    
    // caller
    
    createMask("xxx-xx-xxx") {
        val ssnField = ...
        ssnField::hint
    }
    

    或者,如果您想允许调用者传递任何具有 setter“形式”的函数,请使用 (String) -&gt; Unit 表示“任何接受字符串的函数”。

    fun createMask(mask : String, block: () -> (String) -> Unit) {
        block()(mask)
    }
    
    // caller
    
    createMask("xxx-xx-xxx") {
        val ssnField = ...
        ssnField::hint.setter
    }
    

    请注意,此方法涉及反射,这可能是不可取的。或者,您可以接受一个带有要设置的字符串的闭包,并让调用者在闭包中设置它:

    fun createMask(mask: String, block: (String) -> Unit) {
        block(mask)
    }
    
    // caller
    
    createMask("xxx-xx-xxx") {
        val ssnField = ...
        // note that rather than responsible for returning a property, the caller 
        // is responsible for setting "it" to the property
        ssnField.hint = it
    }
    

    (我假设createMask 不仅仅是设置一个属性。否则它是毫无意义的......)

    【讨论】:

    • 感谢 Sweeper,这看起来很有希望。让我试一试,然后我会将答案标记为“已回答”,如果它有效,我认为它会。
    • 顺便说一句,您建议我阅读哪些参考资料以更熟悉函数指针、KMutableProperty、Unit 等?我发现 Kotlin 函数式语法不是很直观(例如相对于 Javascript 或 Python)。
    • @LanceKind 以下是一些链接:Higher order functions and lambasKMutablePropertyUnit 并不是一件复杂的事情。就像void在其他语言中的意思是“没有返回值”。
    • @LanceKind 我在看你的直播。只需执行createMask(mask, {mutablePropertyHere::myProperty }) 请注意::。这使它成为KMutableProperty0&lt;String&gt;
    • @LanceKind 我没想到你对 lambda 或函数类型一无所知。您可能应该阅读this page,最重要的是this section。我确实传递了第二个参数。
    猜你喜欢
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 2010-12-18
    • 1970-01-01
    • 2019-12-04
    • 1970-01-01
    • 2013-12-15
    • 1970-01-01
    相关资源
    最近更新 更多