一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 4 天,点击查看活动详情
翻译: levinhu 校对: jiajianchen
条目 4:不要暴露自动推断类型
TL;DR
- 进行赋值时,自动推断的类型是等号右边成员的类型,而不是父类或者接口;
- 推断类型容易随着项目迭代而发生可能的变化;
- 明确类型不仅能够提高可读性,而且也能提高 API 的安全性
Kotlin 类型推断是最受欢迎的 Kotlin 特性之一 ,以至于在 Java 10 中也引入了类型推断(相对于 Koltin 还有一些限制)。然而这种特性使用存在一些危险的使用方式。总而言之:我们时刻需要记住赋值的推断类型是右边的类型,不是其父类和接口。
open class Animal
class Zebra: Animal()
fun main() {
var animal = Zebra()
animal = Animal() // 错误:类型不匹配
}
在大多数情况下,这不是一个问题,当面临严格的类型推断时,我们只需要明确类型就可以解决:
open class Animal
class Zebra: Animal()
fun main() {
var animal: Animal = Zebra()
animal = Animal()
}
尽管当我们不需要操作其他库或者模块时,这种做法可能不太便利,但是暴露推断类型可能会很危险。
让我们看一个例子:我们声明如下汽车工厂接口:
interface CarFactory {
fun produce(): Car
}
并且有一个默认的汽车声明:
val DEFAULT_CAR: Car = Fiat126P()
同时,因为在大多数汽车工厂中生产的汽车都是上述默认的汽车,你默认实现工厂接口。同时你认为 DEFAULT_CAR
是汽车了,所以你缺省了类型:
interface CarFactory {
fun produce() = DEFAULT_CAR
}
在此之后,其他开发就会去查看 DEFAULT_CAR
的类型,并且推断当前接口返回的类型应该是 Fiat126P
:
val DEFAULT_CAR = Fiat126P()
现在所有的工厂就只能生产 Fiat126P
。如果这个接口只有你自己在使用,你可能很快就能发现问题并且修复它。但是如果这是一个对外的 API (可能被外部模块或者不同开发者维护的代码调用的类、方法、对象等,例如,库中的 public
、 protected
类、方法和对象声明),你可能会收到一些非常愤怒的反馈。
除此之外,明确返回类型不管是对不熟悉 API 的人而言,或者是为了代码可读性,都是特别重要的信息,因此我们应该让 API 返回类型特别精确。
总结
如果不确定返回类型,我们应该明确它,这是非常重要的信息。如书中条目 14:明确不清晰的变量类型也有提到。
同时,为了提高对外 API 的安全性,我们也应该始终明确类型。在开发项目中,自动推断的类型可能限制性太大,或者太容易更改,我们不能让这样的事情发生。