何时使用扩展方法?

我正在编写Kotlin代码,其中一个特性是扩展方法,除了使用的语法类似于实例方法调用之外,它们与普通函数实际上是相同的。

正常功能

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

扩展方法

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

据我所知,C#扩展方法的工作原理类似。

原则上,通过将第一个参数的类型移动到函数名称的左侧并相应地调整函数体和调用网站(如本例中),可以将任何非零函数写成扩展方法。

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

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

扩展名是静态解析的

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

我们要强调的是,扩展功能是静态调度的,即它们不是按接收机类型虚拟的

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

当您进行扩展功能或“常规”功能时,它更像是一种设计选择。

我向你推荐以下内容:只要你有一个函数,你可以用一个工具类(例如StringUtil.isNullOrEmpty(String)来写一个工具函数,就可以使用扩展函数。 其余部分用作“正常”功能。

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

如果您无法访问源代码,则可以编写扩展名。 在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允许接口方法的实现。)

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

它们主要用于两件事情:

扩展你没有直接控制的类型。 在C#中的一个常见的例子是ForEach()函数扩展IEnumerable(列表的基本类型等)与一个方法应用到所有项目的行动:

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

Helper函数可以简化对自己的类的常见调用,但不保证类中有自己的方法,或者不希望成为API的一部分。