【问题标题】:Kotlin extension functions vs member functions?Kotlin 扩展函数与成员函数?
【发布时间】:2017-11-08 13:55:19
【问题描述】:

我知道 Kotlin 中使用扩展函数来扩展类的功能(例如,来自库或 API 的功能)。

但是,在代码可读性/结构方面,使用扩展函数是否有任何优势:

class Foo { ... }

fun Foo.bar() {
    // Some stuff
}

相对于成员函数:

class Foo {

    ...

    fun bar() {
        // Some stuff
    }
}

?

有推荐的做法吗?

【问题讨论】:

标签: kotlin kotlin-extension


【解决方案1】:

何时使用成员函数

如果满足以下所有条件,您应该使用成员函数:

  • 代码最初是用 Kotlin 编写的
  • 可以修改代码
  • 该方法很有意义,可以从任何其他代码中使用

何时使用扩展函数

如果满足以下任一条件,您应该使用扩展函数:

  • 代码最初是用 Java 编写的,您想添加用 Kotlin 编写的方法
  • 您不能更改原始代码
  • 您需要一个仅对代码的特定部分有意义的特殊函数

为什么?

通常,成员函数比扩展函数更容易找到,因为它们保证在它们所属的类(或超类/接口)中。

它们也不需要导入到所有使用它们的代码中。

【讨论】:

    【解决方案2】:

    在我看来,使用扩展函数有两个令人信服的理由:

    1. 要“扩展”您不是作者/无法更改的类的行为(并且继承没有意义或不可能)。

    2. 为特定功能提供范围。例如,可以将扩展函数声明为独立函数,在这种情况下,它可以在任何地方使用。或者您可以选择将其声明为另一个类的(私有)成员函数,在这种情况下,它只能在该类内部使用。

    听起来#1 在你的情况下不是问题,所以它实际上更多地归结为 #2。

    【讨论】:

    • 是的,我是该课程的原作者(它是针对个人项目的),所以#1 不是问题。您能否通过为特定功能提供范围来准确解释您的意思?谢谢。
    • @FarbodSalamat-Zadeh - 我在 #2 中添加了一些细节 - 如果这有助于澄清,请告诉我。
    • 谢谢,太好了!
    • #2的详细解释可以在here找到。
    【解决方案3】:

    扩展函数类似于您创建的实用函数。

    一个基本的例子是这样的:

    // Strings.kt
    fun String.isEmail() : Boolean {
        // check for email pattern and return true/false
    }
    

    这段代码可以写成 Java 中的实用函数,如下所示:

    class StringUtils {
        public static boolean isEmail(String email) {
            // check for email pattern and return true/false
        }
    }
    

    所以它本质上所做的是,调用与您调用的对象相同的函数将作为第一个参数传递给参数。就像我在Java 中给出的例子一样。

    如果你想从java调用kotlin中创建的扩展函数,你需要将调用者作为第一个参数传递。喜欢,

    StringsKt.isEmail("example@example.com")
    

    根据文档,

    扩展实际上并不修改它们扩展的类。通过定义扩展,您无需将新成员插入到类中,而只是使新函数可以使用这种类型的变量的点符号来调用。

    它们是简单的静态函数,调用者作为第一个参数,其他参数紧随其后。它只是扩展了我们以这种方式编写它的能力。

    何时创建扩展函数?

    • 当您无权访问该类时。当该类属于您尚未创建的某个库时。
    • 对于原始类型。 Int、Float、String 等。

    使用扩展函数的另一个原因是,您不必为了使用方法而扩展该类,就好像它们属于该类(但实际上不是该类的一部分)。

    希望它能让你明白一点..

    【讨论】:

      【解决方案4】:

      正如其他答案中提到的,扩展函数主要用于您无法更改的代码 - 也许您想将某些库对象周围的复杂表达式更改为更容易和更易读的表达式。

      我的想法是为data classes 使用扩展函数。我的推理纯粹是哲学上的,data classes 应该只用作数据载体,它们不应该携带状态,它们本身不应该做任何事情。这就是为什么我认为你应该使用扩展函数,以防你需要围绕data class编写一个函数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-28
        • 1970-01-01
        • 2018-07-03
        • 1970-01-01
        相关资源
        最近更新 更多