热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Kotlin中扩展函数的惯用用法及其合理性

本文讨论了Kotlin中扩展函数的一些惯用用法以及其合理性。作者认为在某些情况下,定义扩展函数没有意义,但官方的编码约定支持这种方式。文章还介绍了在类之外定义扩展函数的具体用法,并讨论了避免使用扩展函数的边缘情况。作者提出了对于扩展函数的合理性的质疑,并给出了自己的反驳。最后,文章强调了在编写Kotlin代码时可以自由地使用扩展函数的重要性。

我看到 Kotlin 中扩展函数的一些用法我个人认为这没有意义,但似乎有一些指导方针“显然”支持它(解释问题)。

具体来说:在类之外(但在同一个文件中)定义一个扩展函数:

data class AddressDTO(val state: State,
val zipCode: String,
val city: String,
val streetAddress: String
)
fun AddressDTO.asXyzFormat() = "${streetAddress}n${city}n${state.name} $zipCode"

其中asXyzFormat()被广泛使用,并且不能被定义为专用/内部(也为情况下,可能)。

在我的常识中,如果您拥有代码 ( AddressDTO) 并且用法不是某个类/模块的本地(因此是私有/内部) - 没有理由定义扩展函数 - 只需将其定义为成员函数班级。


  • 边缘情况:如果你想避免从get-开始的函数序列化- 注释类以获得所需的行为(例如@JsonIgnore在函数上)。这个恕我直言仍然不能证明扩展功能是合理的。

我对此的反驳是,官方 Kotlin 编码约定支持这种方式的扩展功能。具体来说:

自由地使用扩展函数。每次你有一个主要作用于一个对象的函数时,考虑使它成为一个接受该对象作为接收者的扩展函数。

来源

和:

特别是,当为与该类的所有客户端相关的类定义扩展函数时,请将它们放在定义类本身的同一文件中。在定义仅对特定客户端有意义的扩展函数时,将它们放在该客户端的代码旁边。不要创建文件只是为了保存“Foo 的所有扩展名”。

来源

我将感谢任何普遍接受的来源/参考解释为什么将函数移动为类的成员和/或实用参数支持这种分离更有意义。

回答


关于自由使用扩展函数的引用,我很确定意味着自由使用它们而不是顶级非扩展函数(而不是使它成为成员函数)。这是说,如果顶级函数在概念上适用于目标对象,则更喜欢扩展函数形式。

我之前曾搜索过为什么在处理拥有源代码的类时可能选择将函数作为扩展函数而不是成员函数的答案,但从未从 JetBrains 找到规范的答案。以下是我认为您可能会遇到的一些原因,但有些原因很受意见的影响。


  • 有时您需要一个函数来操作具有特定泛型类型的类。想想List.sum(),它仅适用于 Lists 的子集,而不适用于 List 的子类型。

  • 接口可以被认为是契约。接口执行某些操作的函数在概念上可能更有意义,因为它们不是合同的一部分。我认为这是 Iterable 和 Sequence 的大多数标准库扩展函数的基本原理。如果您认为数据类几乎像一个被动结构,则类似的原理可能适用于数据类。

  • 扩展函数提供了允许用户伪覆盖它们的可能性,但强制它们以独立的方式进行。假设你asXyzFormat()是一个开放的成员函数。在其他一些模块中,您收到 AddressDTO 实例并希望以您期望的格式获取它们的 XYZ 格式。但是您收到的 AddressDTO可能已被覆盖asXyzFormat()并为您提供了一些意想不到的东西,所以现在您不能信任该功能。如果您使用扩展功能,那么您允许用户asXyzFormat()用适用于该空间的内容替换他们自己的包中的内容,但您始终可以信任asXyzFormat()源包中的功能。



  • 与接口类似,具有默认实现的成员函数会邀请用户覆盖它。作为接口的作者,您可能需要一个可靠的函数,您可以在该接口上使用具有预期行为的函数。尽管最终用户可以通过重载将您的扩展隐藏在他们自己的模块中,但这不会影响您自己对该功能的使用。

就其价值而言,我认为当您拥有类(而不是接口)的源代码时,很少会选择为类(而不是接口)制作扩展函数。我想不出标准库中的任何例子。这让我相信编码约定文档在包括接口的自由意义上使用“类”一词。






推荐阅读
  • 本文介绍了如何利用ObjectMapper实现JSON与JavaBean之间的高效转换。ObjectMapper是Jackson库的核心组件,能够便捷地将Java对象序列化为JSON格式,并支持从JSON、XML以及文件等多种数据源反序列化为Java对象。此外,还探讨了在实际应用中如何优化转换性能,以提升系统整体效率。 ... [详细]
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • Android中将独立SO库封装进JAR包并实现SO库的加载与调用
    在Android开发中,将独立的SO库封装进JAR包并实现其加载与调用是一个常见的需求。本文详细介绍了如何将SO库嵌入到JAR包中,并确保在外部应用调用该JAR包时能够正确加载和使用这些SO库。通过这种方式,开发者可以更方便地管理和分发包含原生代码的库文件,提高开发效率和代码复用性。文章还探讨了常见的问题及其解决方案,帮助开发者避免在实际应用中遇到的坑。 ... [详细]
  • 本文详细介绍了使用 Python 进行 MySQL 和 Redis 数据库操作的实战技巧。首先,针对 MySQL 数据库,通过 `pymysql` 模块展示了如何连接和操作数据库,包括建立连接、执行查询和更新等常见操作。接着,文章深入探讨了 Redis 的基本命令和高级功能,如键值存储、列表操作和事务处理。此外,还提供了多个实际案例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 【图像分类实战】利用DenseNet在PyTorch中实现秃头识别
    本文详细介绍了如何使用DenseNet模型在PyTorch框架下实现秃头识别。首先,文章概述了项目所需的库和全局参数设置。接着,对图像进行预处理并读取数据集。随后,构建并配置DenseNet模型,设置训练和验证流程。最后,通过测试阶段验证模型性能,并提供了完整的代码实现。本文不仅涵盖了技术细节,还提供了实用的操作指南,适合初学者和有经验的研究人员参考。 ... [详细]
  • Netty框架中运用Protobuf实现高效通信协议
    在Netty框架中,通过引入Protobuf来实现高效的通信协议。为了使用Protobuf,需要先准备好环境,包括下载并安装Protobuf的代码生成器`protoc`以及相应的源码包。具体资源可从官方下载页面获取,确保版本兼容性以充分发挥其性能优势。此外,配置好开发环境后,可以通过定义`.proto`文件来自动生成Java类,从而简化数据序列化和反序列化的操作,提高通信效率。 ... [详细]
  • Python 中 json.dumps() 和 json.loads() 的使用方法详解——Python 面试与 JavaScript 面试必备知识
    在 Python 中,`json.dumps()` 和 `json.loads()` 是处理 JSON 数据的核心函数。`json.dumps()` 用于将字典或其他可序列化对象转换为 JSON 格式的字符串,而 `json.loads()` 则用于将 JSON 字符串解析为 Python 对象。本文详细介绍了这两个函数的使用方法及其在 Python 和 JavaScript 面试中的重要性,帮助读者掌握这些关键技能。 ... [详细]
  • 利用树莓派畅享落网电台音乐体验
    最近重新拾起了闲置已久的树莓派,这台小巧的开发板已经沉寂了半年多。上个月闲暇时间较多,我决定将其重新启用。恰逢落网电台进行了改版,回忆起之前在树莓派论坛上看到有人用它来播放豆瓣音乐,便萌生了同样的想法。通过一番调试,终于实现了在树莓派上流畅播放落网电台音乐的功能,带来了全新的音乐享受体验。 ... [详细]
  • 在Java项目中,当两个文件进行互相调用时出现了函数错误。具体问题出现在 `MainFrame.java` 文件中,该文件位于 `cn.javass.bookmgr` 包下,并且导入了 `java.awt.BorderLayout` 和 `java.awt.Event` 等相关类。为了确保项目的正常运行,请求提供专业的解决方案,以解决函数调用中的错误。建议从类路径、依赖关系和方法签名等方面入手,进行全面排查和调试。 ... [详细]
  • 在当前的软件开发领域,Lua 作为一种轻量级脚本语言,在 .NET 生态系统中的应用逐渐受到关注。本文探讨了 Lua 在 .NET 环境下的集成方法及其面临的挑战,包括性能优化、互操作性和生态支持等方面。尽管存在一定的技术障碍,但通过不断的学习和实践,开发者能够克服这些困难,拓展 Lua 在 .NET 中的应用场景。 ... [详细]
  • 清华大学出版社 | 杨丹:基于MATLAB机器视觉的黑色素瘤皮肤癌检测技术及源代码分析(第1689期)
    清华大学出版社 | 杨丹:基于MATLAB机器视觉的黑色素瘤皮肤癌检测技术及源代码分析(第1689期) ... [详细]
  • 本文详细探讨了MySQL数据库实例化参数的优化方法及其在实例查询中的应用。通过具体的源代码示例,介绍了如何高效地配置和查询MySQL实例,为开发者提供了有价值的参考和实践指导。 ... [详细]
  • PHP服务接口的专业测试方法与实践 ... [详细]
  • 设计实战 | 10个Kotlin项目深度解析:首页模块开发详解
    设计实战 | 10个Kotlin项目深度解析:首页模块开发详解 ... [详细]
  • 本文探讨了Android系统中支持的图像格式及其在不同版本中的兼容性问题,重点涵盖了存储、HTTP传输、相机功能以及SparseArray的应用。文章详细分析了从Android 10 (API 29) 到Android 11 的存储规范变化,并讨论了这些变化对图像处理的影响。此外,还介绍了如何通过系统升级和代码优化来解决版本兼容性问题,以确保应用程序在不同Android版本中稳定运行。 ... [详细]
author-avatar
手机用户2702935897
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有