Kotlin:扩展函数的惯用用法-将扩展函数放在它扩展的类旁边
我在Kotlin中看到了一些扩展函数的用法,我个人认为这是没有意义的,但似乎有一些“显然”支持它的准则(解释问题) 特别是:在类外部(但在同一文件中)定义扩展函数:Kotlin:扩展函数的惯用用法-将扩展函数放在它扩展的类旁边,kotlin,extension-function,Kotlin,Extension Function,我在Kotlin中看到了一些扩展函数的用法,我个人认为这是没有意义的,但似乎有一些“显然”支持它的准则(解释问题) 特别是:在类外部(但在同一文件中)定义扩展函数: 数据类地址dto(val state:state, val zipCode:String, 瓦尔市:字符串, val streetAddress:字符串 ) fun AddressDTO.asXyzFormat()=“${streetAddress}\n${city}\n${state.name}$zipCode” 其中,asXy
数据类地址dto(val state:state,
val zipCode:String,
瓦尔市:字符串,
val streetAddress:字符串
)
fun AddressDTO.asXyzFormat()=“${streetAddress}\n${city}\n${state.name}$zipCode”
其中,asXyzFormat()
被广泛使用,不能定义为私有/内部(但在可能的情况下也是如此)
根据我的常识,如果您拥有代码(AddressDTO
),并且该用法不是某个类/模块的本地用法(因此属于私有/内部)-没有理由定义扩展函数-只需将其定义为该类的成员函数即可
- 边缘大小写:如果要避免以
开头的函数序列化,请注释类以获得所需的行为(例如,函数上的get
)。这个IMHO仍然不能证明扩展函数的合理性@JsonIgnore
我将感谢任何普遍接受的源代码/参考,解释为什么将函数移动为类的成员更有意义,和/或实用参数支持这种分离。这里有一个相反的参数 向语言中添加扩展函数的主要原因之一是能够从标准库、第三方库和其他依赖项向类中添加功能,在这些依赖项中,您无法控制代码,也无法添加成员函数(也称为方法).我怀疑这主要是编码惯例的那一部分所讨论的那些案例 在Java中,这种情况下唯一的选择是实用方法:静态方法,通常在一个实用类中,聚集了大量这样的方法,每个方法都将相关对象作为其第一个参数:
public static String[] splitOnChar(String str, char separator)
public static boolean isAllDigits(String str)
……等等,没完没了
这里的主要问题是很难找到这样的方法(除非您已经知道所有各种实用程序类,否则IDE不会提供任何帮助)。此外,调用它们也很冗长(尽管在静态导入可用后它会有所改进)
Kotlin的扩展方法在字节码级别以完全相同的方式实现,但它们的语法更简单,与成员函数完全相同:它们以相同的方式编写(使用this
&c),调用它们看起来就像调用成员函数,您的IDE会建议它们
(当然,它们也有缺点:没有动态分派、没有继承或重写、范围/导入问题、名称冲突、对它们的引用不方便、从Java或反射访问它们不方便等等。)
所以:如果扩展函数的主要目的是在成员函数不可能的情况下替换成员函数,那么为什么在成员函数可能的情况下使用它们呢强>
(公平地说,您可能需要它们的原因有几个。例如,您可以使接收器为空,这在成员函数中是不可能的。但在大多数情况下,正确的成员函数的好处远远超过了它们。)
这意味着绝大多数扩展函数可能是为您不控制源代码的类编写的,因此您没有将它们放在类旁边的选项。关于自由使用扩展函数的引述,我很确定,这意味着可以自由地使用它们,而不是顶级的非扩展函数(而不是将其作为成员函数)。这意味着,如果顶级函数在概念上对目标对象起作用,则首选扩展函数形式 我以前搜索过一个问题的答案,为什么在处理一个拥有源代码的类时,您可能会选择将函数作为扩展函数而不是成员函数,但从未从JetBrains中找到一个规范的答案。这里有一些原因,我认为你可能会,但有些是高度受意见
- 有时,您需要在具有特定泛型类型的类上操作的函数。想想
,它只对列表的子集可用,而不是列表的子类型List.sum()
- 接口可以看作是契约。对接口执行某些操作的函数在概念上可能更有意义,因为它们不是契约的一部分。我认为这是Iterable和Sequence的大多数标准库扩展函数的基本原理。如果您认为数据类几乎像被动结构,那么类似的原理可能适用于数据类
- 扩展函数提供了允许用户伪覆盖它们的可能性,但强制用户以独立的方式进行。假设您的
是一个开放成员函数。在其他一些模块中,您接收AddressDTO实例,并希望获得它们的XYZ格式,完全符合您期望的格式。但是您收到的地址可能已经覆盖了asXyzFormat()