在 Kotlin 中,具有至少一个参数的函数可以定义为常规非成员函数或 extension function一个参数是接收者。
至于作用域,似乎没有区别:两者都可以在类和其他函数内部或外部声明,并且两者都可以或不能具有同等的可见性修饰符。
语言引用似乎不建议针对不同情况使用常规函数或扩展函数。
所以,我的问题是:什么时候扩展函数比普通的非成员函数更有优势?什么时候普通函数优于扩展?
foo.bar(baz, baq)
vs bar(foo, baz, baq)
.
这只是函数语义的暗示(接收器绝对是焦点)还是存在使用扩展函数使代码更清晰或开辟机会的情况?
最佳答案
扩展函数在少数情况下很有用,而在其他情况下则是强制性的:
惯用案例:
当您想要增强、扩展或更改现有 API 时。扩展函数是通过添加新功能来更改类的惯用方式。您可以添加extension functions和 extension properties .参见 Jackson-Kotlin Module 中的示例用于向 ObjectMapper
类添加方法,以简化 TypeReference
和泛型的处理。
为无法在 null
上调用的新方法或现有方法添加 null 安全性。例如,String?.isNullOrBlank()
的 String 的扩展函数允许您甚至在 null
字符串上使用该函数,而无需自己执行 null
首先检查。函数本身在调用内部函数之前进行检查。见 documentation for extensions with Nullable Receiver
强制案例:
当你想要一个接口(interface)的内联默认函数时,你必须使用扩展函数将它添加到接口(interface),因为你不能在接口(interface)声明中这样做(内联函数必须是 final
目前在界面中是不允许的)。这在您需要内联具体化函数时很有用,for example this code from Injekt
当您想将 for (item in collection) { ... }
支持添加到当前不支持该用法的类时。您可以添加一个遵循 for loops documentation 中描述的规则的 iterator()
扩展方法。 -- 即使返回的类似迭代器的对象也可以使用扩展来满足提供 next()
和 hasNext()
的规则。
将运算符添加到现有的类,例如 +
和 *
(#1 的特殊化,但您不能以任何其他方式执行此操作,因此是强制性的)。见 documentation for operator overloading
可选案例:
您想控制调用者何时可以看到某些内容的范围,因此您只能在允许调用可见的上下文中扩展类。这是可选的,因为您可以只允许始终看到扩展名。 see answer in other SO question for scoping extension functions
你有一个接口(interface),你想简化所需的实现,同时仍然允许用户使用更简单的帮助函数。您可以选择为接口(interface)添加默认方法以提供帮助,或者使用扩展函数来添加接口(interface)的非预期实现部分。一种允许覆盖默认值,另一种则不允许(扩展与成员的优先级除外)。
当您想将功能与功能类别相关联时;扩展函数使用它们的接收器类作为找到它们的地方。它们的 namespace 成为可以触发它们的类(或多个类)。而顶级函数将更难找到,并且会填满 IDE 代码完成对话框中的全局 namespace 。您还可以修复现有的库 namespace 问题。例如,在 Java 7 中,您有 Path
类,并且很难找到 Files.exist(path)
方法,因为它的名称间隔很奇怪。该函数可以直接放在 Path.exists()
上。 (@kirill)
优先规则:
在扩展现有类时,请牢记优先规则。它们在 KT-10806 中进行了描述如:
For each implicit receiver on current context we try members, then local extension functions(also parameters which have extension function type), then non-local extensions.
https://stackoverflow.com/questions/35317940/
相关文章:
constructor - 如何在 Kotlin 中扩展具有多个构造函数的类?
android - 在当前主题中找不到样式 'cardView Style'
java - 在 Kotlin 中定义 log TAG 常量的最佳方法是什么?
kotlin - 在 Android Studio 中构建时如何解决错误 "Failed to re
android - 如何在 Android 上使用 Kotlin 显示 Toast?
dictionary - Kotlin 是否有 Map 文字的语法?
kotlin - Kotlin 中的 crossinline 和 noinline 有什么区别?