【问题标题】:When to use extension methods? [duplicate]何时使用扩展方法? [复制]
【发布时间】:2017-10-27 06:19:18
【问题描述】:

我正在编写 Kotlin 代码,它的功能之一是扩展方法,除了您使用的语法看起来像实例方法调用之外,它们实际上与普通函数相同。

普通函数

fun blah(x: Int) { println(x) }
val f = blah(1)

扩展方法

fun Int.blah() { println(this) }
val f = 1.blah()

据我了解,C# 扩展方法的工作方式类似。

原则上,通过将第一个参数的类型移动到函数名称的左侧并相应地调整函数体和调用位置(如本例所示),实际上任何非空函数都可以编写为扩展方法。

那么我应该把我所有的函数都写成扩展方法吗?他们都没有?我应该使用什么原则来决定正常编写哪些函数,以及编写哪个作为输入之一的扩展方法?

【问题讨论】:

  • 一般来说,IMO,你应该避免扩展你不拥有的对象
  • @AlexeiLevenkov 那是关于扩展方法与继承的。我在问扩展方法与普通函数/静态方法。
  • @MarcusHöglund 你为什么这么认为?您可以确定扩展功能的范围。它们不是全球性的。在我看来,在你不拥有的类上编写扩展是扩展函数的最佳用例之一。它让你编写可读的 DSL。

标签: c# kotlin extension-methods


【解决方案1】:

https://kotlinlang.org/docs/reference/extensions.html#extensions-are-resolved-statically

扩展是静态解析的

扩展实际上并不修改它们扩展的类。通过定义一个 扩展,您不会将新成员插入到类中,而只是使 可在 this 的变量上使用点符号调用的新函数 输入。

我们想强调的是,扩展函数是静态地分派的,即它们不是按接收者类型虚拟的

因此,将所有函数编写为扩展方法并不是一个好方法,因为它们是静态分派的。这消除了覆盖它们的能力,例如在派生类中。

当你做一个扩展函数或一个“普通”函数时,它更像是一种设计选择。

我会向您推荐以下内容: 每当您有一个函数,您可以将其编写为具有像 StringUtil.isNullOrEmpty(String) 这样的实用程序类的实用程序函数时,请使用扩展函数。将其余部分用作“正常”功能。

还阅读了 Kotlin 创建扩展的动机: https://kotlinlang.org/docs/reference/extensions.html#motivation

【讨论】:

  • 这对于 OOP 来说是正确的,但是例如,IEnumerable 基于functional programming principles,在这种情况下,拥有静态方法是完全可以的。
  • 同意。当您应该使用扩展方法时,我没有是/否列表。在某些情况下(如您所描述的情况),您或多或少必须使用它,而在其他情况下您不应该使用它。
【解决方案2】:

当您无法访问源代码时,您会编写扩展程序。在 Java 中,您编写实用程序类。

public final class BarUtility {
    public static int foo(Bar i, int j){
        return i.value + j;
    }
}

BarUtility.foo(bar, 1);

在 Kotlin 中,您编写扩展方法。

fun Bar.foo(i: Int): Int = value + i
bar.foo(1)

在 C# 中,它是相同的,但您也可以将它用于接口方法实现。 (Kotlin 允许实现接口方法。)

【讨论】:

    【解决方案3】:

    没有固定的规则,但你不应该把所有的普通函数都写成扩展方法。

    它们主要用于两件事:

    扩展您无法直接控制的类型。 C# 中的一个常见示例是 ForEach() 函数,它扩展了 IEnumerable(列表等的基本类型),并提供了一种将操作应用于所有项目的方法:

    public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
    {
         foreach (T item in enumeration)
         {
            action(item);
         }
    }
    

    帮助函数简化对您自己的类的常见调用,但不保证您的类中有自己的方法,或者您不想成为 API 的一部分。

    【讨论】:

      猜你喜欢
      • 2010-11-14
      • 1970-01-01
      • 2020-12-05
      • 2012-03-01
      • 2012-11-04
      • 2011-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多