【问题标题】:Kotlin top-levels functions vs object functionKotlin 顶级函数与对象函数
【发布时间】:2019-07-18 15:54:50
【问题描述】:

我有静态功能,仅限于某些上下文,例如仅适用于文档。有 2 种替代方法可以将其定义为顶级函数或对象中的函数。

1.

package com.armsoft.mtrade.data.pref

import com.armsoft.mtrade.App
import com.armsoft.mtrade.domain.model.DocSaveType

object DocPrefManager {
    private const val DOC_PREF = "DOC_PREF"

    private const val KEY_ORDER_SAVE_TYPE = "KEY_ORDER_SAVE_TYPE"

    @JvmStatic
    fun setOrderSaveType(orderSaveType: DocSaveType) {
        val context = App.getContext()
        val sharedPreferences = context.getSharedPreferences(DOC_PREF, 0)
        val editor = sharedPreferences.edit()
        editor.putString(KEY_ORDER_SAVE_TYPE, orderSaveType.getCode())
        editor.commit()
    }
}

2.

package com.armsoft.mtrade.data.pref

import com.armsoft.mtrade.App
import com.armsoft.mtrade.domain.model.DocSaveType

fun setOrderSaveType(orderSaveType: DocSaveType) {
    val context = App.getContext()
    val sharedPreferences = context.getSharedPreferences(DocPrefManager.DOC_PREF, 0)
    val editor = sharedPreferences.edit()
    editor.putString(DocPrefManager.KEY_ORDER_SAVE_TYPE, orderSaveType.getCode())
    editor.commit()
}

顶级函数的优点是它没有被包装在一个对象中,缺点是它可以在没有类名前缀的情况下从任何地方访问。这种情况是否有优点或缺点或最佳实践?

【问题讨论】:

    标签: android function kotlin


    【解决方案1】:

    多模块项目的提示:

    使用internal 可见性修饰符将顶级函数的范围限定为其包含模块,这样它就不会污染不相关模块中的 IDE 自动完成功能。

    // module A
    internal fun doSomething() {
        // ...
    }
    
    // module B
    doSomething() // (!) Cannot access 'doSomething': it is internal in module A
                  // Does NOT show up in module B's auto-complete
    

    【讨论】:

      【解决方案2】:

      KotlinConf 2017 - You Can, but Should You? by Mike Gouline 建议我们应该小心使用顶层函数,因为它可能会导致“自动完成污染”。

      但是,顺便说一句,Andrey Breslav 认为顶级函数是他在 KotlinConf 2018 - Closing Panel 中最喜欢的语言功能。

      【讨论】:

        【解决方案3】:

        虽然推荐的方法是尽可能使用顶级声明,但仅在特定上下文中使用的函数应限定在该上下文中并在相关中声明班级。顶级函数对于定义 helperutility 函数特别有用。一个例子是 Java 标准库中的集合函数,它具有真正的全局范围。这同样适用于常数。阅读此答案下的讨论https://stackoverflow.com/a/48820895/1635488

        在您的情况下,DocPrefManager 具有特定的上下文。另外,我想您不想用特定功能污染 IDE 自动完成列表。这会导致不可维护性。

        附: DocPrefManager 函数不应依赖于 App.getContext()。 DocPrefManager 类应该使用上下文初始化,在这种情况下使用顶级函数很奇怪,因为你的函数不会是静态的。

        【讨论】:

          【解决方案4】:
          【解决方案5】:

          object Clazz 将被编译为单例,顶级函数在 JVM 中将被编译为静态。

          如果没有理由让您的方法成为实例,那么静态(顶级,伴随对象)方式会有点高性能。(参考:https://stackoverflow.com/a/11993118/5354658

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-12-08
            • 1970-01-01
            • 2015-10-31
            • 2019-06-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多