Kotlin 函数和扩展 (extension)
前言
本文巩固一下 Kotlin 函数扩展知识点。
本文大纲
1. 回顾 Java 中 Utils 工具类
Utils 是无构造参数的 static 方法集合,主要用于扩展某个对象的功能,如 MathUtils,StringUtils, LogUtils。
Utils 类在一定程度上减少了重复代码的问题,是成本最低的 DRY(Don't repeat yourself)实践。
从代码设计的角度看,Utils 方法是 static 的,没有 OOP 的继承,重写,抽象的特性(static 本身就是反 OOP 的)。且 Utils 违反了单一职责,一个类应该包含其属性和所有操作方法。而 Utils 实现的方法并不在这个类内。
从使用的角度,必须预先知道 Utils 工具类的存在,能使用为这个类添加的扩展方法。 但在实际使用中,这个条件往往是缺失的,在团队开发中,个人无法掌握所有代码,因为不知道这个代码已经有人实现过了,导致都实现了自己的 Utils。所以会导致一个工程里同一个类的 Utils 往往会有好几个。
但存在必然是合理的。从开发者个人角度来看,使用 Utils 而不是对象继承的原因,主要是因为:
无法继承/重写这些类及其方法,只能通过 Utils 扩展;
继承一个类比抽取代码块封装为函数的实现成本+替换成本高;
Utils 绝大情况下只是用来存储代码块,需求非常稳定,无需面向对象。
使用 Utils 的场景里很少会用到面向对象的特性,那么没有面向对象的缺点也并没有那么严重了。抛开 Utils 的设计缺点,是否可以避免使用上的缺点?Kotlin 提供的解决方法就是扩展(extension)。
2. Kotlin 扩展的使用和实现分析
声明一个 Kotlin 扩展如下:
与普通的方法声明很相似,方法名前多了一个类名,表示其归属的类。扩展声明为顶层声明的时候可以被外部调用(因为函数是一等公民,在方法内部也可以声明扩展方法)。
函数体内用 this 来引用调用的实例,属性和方法的访问权限与普通调用一致。一致的意思是和正常在其他方法内部调用的权限一致,并不会因为是扩展声明就可以访问 private/propect 权限的属性和方法。这是因为扩展声明在字节码层面上其实是 static 方法。下面是appendHaha
对应 jvm 字节码的反编译结果:
所以从 Java 的角度来看,Kotlin 的扩展方法和 Utils 的调用没有差别,都是调用类的 static 方法然后传入操作的参数。实际上 Java 想要调用 Kotlin 的扩展方法也确实是这样调用的。
扩展方法的调用和实例方法调用一致,在调用者角度没有区别。
3. 总结
Kotlin 扩展依然没有解决 Utils 类的设计缺点。就像 Kotlin Int 对 Java int,Kotlin property 对 Java field 一样,Kotlin 扩展是 对 Java 不完全面向对象的“清理”,使 Kotlin 更接近完全面向对象。相比 Utils 工具类,Kotlin 扩展特性能有效减少开发者心智负担和沟通成本,从而提高开发效率。
版权声明: 本文为 InfoQ 作者【子不语Any】的原创文章。
原文链接:【http://xie.infoq.cn/article/28b78741fd3ebdca8f3cc70a1】。文章转载请联系作者。
评论