什么时候应该更喜欢 Kotlin 扩展函数?

2024-04-21

在 Kotlin 中,至少有一个参数的函数可以定义为常规非成员函数或定义为扩展功能 https://kotlinlang.org/docs/reference/extensions.html#extension-functions其中一个参数是接收者。

至于作用域,似乎没有什么区别:两者都可以在类和其他函数的内部或外部声明,并且都可以或不可以同等地具有可见性修饰符。

语言参考似乎不建议在不同情况下使用常规函数或扩展函数。

所以,我的问题是:扩展函数什么时候比常规非成员函数更有优势?当常规的超过扩展时?

foo.bar(baz, baq) vs bar(foo, baz, baq).

它只是函数语义的暗示(接收者肯定是焦点)还是在某些情况下使用扩展函数使代码更加简洁或开辟了机会?


扩展函数在某些情况下很有用,但在其他情况下是必需的:

惯用案例:

  1. 当您想要增强、扩展或更改现有 API 时。扩展函数是通过添加新功能来更改类的惯用方法。你可以加扩展功能 https://kotlinlang.org/docs/reference/extensions.html#extension-functions and 扩展属性 https://kotlinlang.org/docs/reference/extensions.html#extension-properties。请参阅中的示例Jackson-Kotlin 模块 https://github.com/FasterXML/jackson-module-kotlin/blob/master/src/main/kotlin/com/fasterxml/jackson/module/kotlin/Extensions.kt#L15-L32用于添加方法到ObjectMapper类简化了处理TypeReference和仿制药。

  2. 向无法调用的新方法或现有方法添加空安全性null。例如 String of 的扩展函数String?.isNullOrBlank()允许您甚至在null字符串而不必自己做null先检查一下。该函数本身在调用内部函数之前进行检查。看Nullable Receiver 扩展的文档 https://kotlinlang.org/docs/reference/extensions.html#nullable-receiver

强制案例:

  1. 当您想要接口的内联默认函数时,必须使用扩展函数将其添加到接口中,因为您不能在接口声明中执行此操作(内联函数必须是final目前接口中不允许这样做)。当您需要内联具体化函数时,这很有用,例如来自 Injekt 的这段代码 https://github.com/kohesive/injekt/blob/master/api/src/main/kotlin/uy/kohesive/injekt/api/Registry.kt#L5-L49

  2. 当你想添加时for (item in collection) { ... }支持当前不支持该用法的类。您可以添加一个iterator()遵循中描述的规则的扩展方法for 循环文档 https://kotlinlang.org/docs/reference/control-flow.html#for-loops-- 即使返回的类似迭代器的对象也可以使用扩展来满足提供的规则next() and hasNext().

  3. 将运算符添加到现有类中,例如+ and *(#1 的专业化,但你不能以任何其他方式做到这一点,所以是强制性的)。看运算符重载的文档 https://kotlinlang.org/docs/reference/operator-overloading.html

可选案例:

  1. 您希望控制某些内容对调用者可见的范围,因此您仅在允许调用可见的上下文中扩展该类。这是可选的,因为您可以允许扩展始终可见。请参阅其他 SO 问题的答案以了解扩展函数的范围 https://stackoverflow.com/a/34797367/3679676

  2. 您有一个界面,您希望简化所需的实现,同时仍然为用户提供更简单的帮助函数。您可以选择为接口添加默认方法来提供帮助,或者使用扩展函数来添加接口中非预期实现的部分。一种允许覆盖默认值,另一种则不允许(扩展与成员的优先级除外)。

  3. 当您想要将功能与功能类别相关联时;扩展函数使用它们的接收器类作为查找它们的位置。它们的名称空间成为可以触发它们的类(或多个类)。而顶级函数将更难找到,并且会填满 IDE 代码完成对话框中的全局名称空间。您还可以修复现有的库名称空间问题。例如,在 Java 7 中,您有Path类并且很难找到Files.exist(path)方法,因为它的名称间隔很奇怪。该函数可以直接放在Path.exists()反而。 (@基里尔)

优先规则:

扩展现有类时,请记住优先级规则。它们的描述见KT-10806 https://youtrack.jetbrains.com/issue/KT-10806#comment=27-1283497 as:

对于当前上下文中的每个隐式接收器,我们尝试成员,然后是本地扩展函数(也是具有扩展函数类型的参数),然后是非本地扩展。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么时候应该更喜欢 Kotlin 扩展函数? 的相关文章

  • Kotlin 中的数据绑定无法与视图绑定一起使用

    安卓工作室3 6 构建 gradle buildscript ext kotlin version 1 3 50 repositories google jcenter dependencies classpath com android
  • 在 Android 中处理多个回收器视图 [Kotlin]

    我遇到过这样的情况 一个布局上有 3 个 RecyclerView 他们以某种方式相互依赖 数据来自房间数据库 问题原型 问题陈述 假设您有类似 Floor1 Floor2 Floor3 等 的楼层 并且每个楼层内都有类似 Room1 Ro
  • 如何在 IntelliJ 中快速文档中换行文本?

    Ctrl Q 快速文档 后我看不到所有文本 我必须水平滚动才能看到所有内容 我无法使编辑器适合窗口 更新 问题只是符号定义 即 第一行 描述 块文本 正确换行 实际上 我不想调整此窗口的大小 因为我更喜欢将其保留在相同的位置以便快速参考 我
  • @Service 中带有 Kotlin 的 Spring Boot @Autowired 始终为 null

    目前 我尝试使用 Kotlin 重写我的 Java Spring Boot 应用程序 我遇到了一个问题 在我所有的类中都用 Service依赖注入无法正常工作 所有实例都null 这是一个例子 Service Transactional o
  • 在 Kotlin 中以编程方式更改区域设置

    我有一些在 Java 中以编程方式更改语言环境的代码 但是当我的应用程序迁移到 Kotlin 时 我无法再更改区域设置 例如 Java 中的这段代码运行得非常好 public static final void setAppLocale S
  • 喷气背包组合中的波纹效果无法正常工作

    我正在研究jetpack compose中的连锁反应 我提供了我的颜色 单击视图后 它会在一段时间后显示不同类型的颜色 在按下状态时显示为深灰色 binding itemComposable setContent Column modifi
  • 为什么 Kotlin 数据类对象有反引号?

    这是我使用 Kotlin 数据类创建器插件创建的数据类 data class ResponseHealthInisghts val data List
  • 如何在发布版本中使用 Zebra EMDK?

    所以我有一台 Zebra MC330M 设备 我之前创建了一个应用程序 我想使用 PDA 内置的条形码扫描仪 如果在调试模式下运行我的应用程序 一切正常 我可以读取条形码 但是如果我创建暂存或释放版本 apk 则条形码读取器不活动 因此如果
  • 双击事件 - 多个范围

    我正在寻找为双击事件在多个范围内进行编码的最佳方法 Private Sub Worksheet BeforeDoubleClick ByVal Target As Range Cancel As Boolean If Not Interse
  • Android:如何根据视图模型实时数据属性为片段编写单元测试?

    我的片段 UI 中有一个列表视图 其元素集取决于来自视图模型 LiveData 属性的值的状态 我想为片段创建工具测试 该片段包含与该属性的值集相关的 3 个场景测试用例 但我不知道从哪里开始 我的代码应该如下所示 class MyView
  • 使用 Kotlin 协程替换 LocalBroadcastManager 以进行 Firebase 消息传递

    使用时Firebase 云消息传递 https firebase google com docs cloud messaging android client在 Android 上 通常需要通知当前Activity传入的推送通知 推荐的方法
  • 在Android中绘制圆角矩形

    我已经发现这个问题 https stackoverflow com questions 5618402 how to draw rounded rectangle in android ui解决方案是这段代码
  • 错误:链接引用失败。 -> 排队作业

    我正在使用 Kotlin 学习 Android Material Design 一切都很顺利 直到我尝试使用 android support design widget FloatingActionButton 当我重建项目时 我收到以下错
  • 在viewpager2中禁用动画

    我有 viewpager2 和扩展 FragmentStateAdapter 的适配器 我希望用户仅通过单击选项卡布局即可转到另一个页面 我已禁用此 viewpager2 的用户输入 但是当我单击选项卡时 有页面之间快速滑动的动画 但我只想
  • 用于 Kotlin 中单元测试的 BuildConfigField 模拟

    我正在尝试尽可能多地涵盖Kotlin Android 库我遇到了有关自定义 BuildConfig 变量的问题 更广为人知的是buildConfigField 我想模拟这个变量来测试两者true and false values 从 Gra
  • Jetpack Compose:制作全屏(绝对定位)组件

    我怎样才能在全屏渲染树的深处制作一个可组合的 类似于Dialog可组合作品 例如 当用户单击图像时 它会显示该图像的全屏预览 而无需更改当前路线 我可以用 CSS 来做到这一点position absolute or position fi
  • Kotlin 未解决的参考:CLI 上 gradle 的 println

    放一个printlnkotlin 函数返回之前的语句会崩溃 堆栈跟踪 thufir dur NetBeansProjects kotlin thufir dur NetBeansProjects kotlin gradle clean bu
  • Android Room 数据库 - 未解析的引用 @Entity 和其他注释

    我在我的应用程序中使用 Android Room Persistence 库 v 1 0 0 alpha1 虽然它工作正常 但当我在 Android studio 中打开模型类 Kotlin 数据类 时 它显示用于 Room 数据库的所有注
  • 在 Android Studio 中运行单个 .kt 文件

    我在 Android Studio 中创建了一个 Scratch Kotlin 文件 我只想运行这个 scrap kt 文件并获取输出 我摆弄了运行配置 但无法理解主类中将包含什么 If you create a top level fun
  • SharedFlow 和 StateFlow 的主要区别

    两者有什么区别共享流 and 状态流 以及如何使用这些MVI建筑学 使用简单更好吗Flow或者这些作为状态和事件 Flow 是冷的 意味着它仅在收集数据时才发出数据 另外Flow不能保存数据 可以把它看成是水在里面流动的管道 Flow中的数

随机推荐

  • 删除 ThreadPoolExecutor 的所有排队任务

    我有一个相当简单的问题线程池执行器 http java sun com javase 6 docs api java util concurrent ThreadPoolExecutor html 我遇到以下情况 我必须使用队列中的对象 为
  • DynamoDB:键及其含义

    我对如何使用 DynamoDB 表键感到困惑 该文档提到了 HASH 似乎也称为分区 键和 RANGE 或排序 键 我试图将这些与我之前对数据库索引理论的理解大致保持一致 我目前主要基于猜测的理解是 HASH 键本质上是主键 它必须是唯一的
  • Spring 部分更新对象数据绑定

    我们正在尝试在 Spring 3 2 中实现一个特殊的部分更新功能 我们使用 Spring 作为后端 并有一个简单的 Javascript 前端 我无法找到满足我们要求的直接解决方案 即update 函数应该接受任意数量的 field va
  • 我可以在乳胶文档的标题中使用 knitr 内联表达式吗?

    我想使用 Knit Sweave 内联调用 Sexpr 在 LaTeX 文档的标题中 在 begin document 命令之后但在 maketitle 命令之前 内联 R 代码将从我嵌入 LaTeX 的 R 脚本早期创建的 R 数据帧中提
  • sqlite只支持1笔交易?

    在使用 ADO NET 时 也许我错了 我不知道它叫什么 我注意到我只能通过连接开始事务 并且命令似乎有 command Transaction 获取事务数据但不启动事务本身 实际上 在查看时我在 System Data SQLite 中看
  • typeid 运算符的奇怪行为?

    使用 XCode 3 2 3 64 位 我得到以下奇怪的输出 我究竟做错了什么 include
  • Willpopscope 无法在 Web 上拦截浏览器后退按钮

    我尝试过拦截网络上的后退按钮 但它不会被触发 我怎样才能让它发挥作用 WillPopScope onWillPop print will pop on web Get offNamed orders return new Future gt
  • grunt-wiredep 对具有不同依赖关系的多个文件

    目前的项目结构有点像这样 index html bower json bower components 建议的项目结构将在项目根目录中添加更多静态 html 文件 到目前为止 我一直在管理 Bower json 中的所有前端依赖项 并使用
  • 在多个自定义模块支持的多个脚本中使用 python 的 argparse

    我正在构建一组用于管理我们的基础设施的脚本和模块 为了让事情井井有条 我想整合尽可能多的努力 并尽量减少新脚本的样板代码 特别是这里的问题是整合 ArgumentParser 模块 一个示例结构是让脚本和库组织如下 bin script1
  • 如何在 C++ 中调用不同项目的方法?

    使用 Visual Studio 时 我通常使用 C 工作 因此 C 中的某些内容让我感到困惑 概念看起来如此不同 但名称几乎相同 我创建了一个控制台项目 我想在其中运行另一个项目以进行测试 我将该项目添加为控制台应用程序的引用 然后陷入困
  • 如何将图像文件从文档目录上传到iphone中的php服务器

    我目前正在开发画廊类的 iPhone 应用程序 根据我的要求 我需要将所有相机捕获的图像存储到文档目录中 文档文件夹中有一些 10 20 个图像文件 之后我必须使用单个 php url 将应用程序资源文档文件夹推送到服务器上 我已附加屏幕截
  • C# 中的省略号表示法?

    我在哪里可以获得有关实现我自己的带有省略号符号的方法的信息 e g static void my printf char format 这也是所谓的省略符号还是有一个更奇特的名字 看看参数关键字 https learn microsoft
  • 多边形来自折线?

    我正在尝试自动从折线创建多边形 到目前为止 我一直在正确计算折线每个部分的外推边 条件 基线和边之间的距离是常数 如何从基点 红色点 计算边 蓝色点 的角点 这是我在 Qt 中的代码 这对我来说很好用 QPolygonF projectPL
  • 使用 BeautifulSoup 抓取网页中的链接标题和 URL

    我有一个流行文章的网页 我想抓取每个引用网页的超链接及其所显示文章的标题 我的脚本所需的输出是一个 CSV 文件 其中在一行中列出了每个标题和文章内容 因此 如果该网页上有 50 篇文章 我想要一个包含 50 行和 100 个数据点的文件
  • Hibernate - 限制嵌套集合的大小

    我有以下型号 Entity Data public class Book Id GeneratedValue strategy GenerationType IDENTITY private Long id private String a
  • SwiftUI macOS 在文本字段处于活动状态时使用箭头键滚动列表

    我想使用 SwiftUITextField https developer apple com documentation swiftui textfield和一个 SwiftUIList https developer apple com
  • 使用 C# 获取 Active Directory 用户数据

    我想获取有关特定用户的数据 我知道该用户的 OU 路径 但无法使用该 OU 路径获取信息 总是说找不到用户 谁能告诉我我需要更改搜索过滤器吗 请帮忙 Code 用户路径 abc ds xyz net fGroup xcxc Users 12
  • Spring data Cassandra 对 UDT 的注释 [重复]

    这个问题在这里已经有答案了 springdatacassandra如何支持POJO中Cassandra提供的用户定义数据类型 我正在寻找 UDT 的注释 Spring data cassandra 最新版本 1 2 0 BUILD SNAP
  • 在 Google Chrome 中使用“i18n-content”进行国际化

    The 官方文档 http code google com chrome extensions i18n html建议检索字符串以进行国际化 如下所示 document querySelector appname innerHTML chr
  • 什么时候应该更喜欢 Kotlin 扩展函数?

    在 Kotlin 中 至少有一个参数的函数可以定义为常规非成员函数或定义为扩展功能 https kotlinlang org docs reference extensions html extension functions其中一个参数是