- Introduction
- Part 1 Good Code
- Chapter 1 Safety
- 引言
- 第1条:限制可变性
- 第2条:最小化变量作用域
- 第3条:尽快消除平台类型
- 第4条:不要把推断类型暴露给外部
- Item 5 Specify Your Expectations On Arguments And State
- 第6条:尽可能使用标准库中提供的异常
- 第7条:当不能返回预期结果时,优先使用null o或Failure 作为返回值
- Item 8 Handle Nulls Properly
- 第9条:使用use关闭资源
- Item 10 Write Unit Tests
- Chapter 2 Readability
- Introduction
- Item 11 Design For Readability
- Item 12 Operator Meaning Should Be Consistent With Its Function Name
- Item 13 Avoid Returning Or Operating On Unit
- Item 14 Specify The Variable Type When It Is Not Clear
- Item 15 Consider Referencing Receivers Explicitly
- Item 16 Properties Should Represent State Not Behavior
- Item 17 Consider Naming Arguments
- Item 18 Respect Coding Conventions
- Part 2 Code Design
- Chapter 3 Reusability
- Introduction
- Item 19 Do Not Repeat Knowledge
- Item 20 Do Not Repeat Common Algorithms
- Item 21 Use Property Delegation To Extract Common Property Patterns
- Item 22 Use Generics When Implementing Common Algorithms
- Item 23 Avoid Shadowing Type Parameters
- Item 24 Consider Variance For Generic Types
- Item 25 Reuse Between Different Platforms By Extracting Common Modules
- Chapter 4 Abstraction Design
- Introduction
- Item 26 Each Function Should Be Written In Terms Of A Single Level Of Abstraction
- Item 27 Use Abstraction To Protect Code Against Changes
- Item 28 Specify API Stability
- Item 29 Consider Wrapping External API
- Item 30 Minimize Elements Visibility
- Item 31 Define Contract With Documentation
- Item 32 Respect Abstraction Contracts
- Chapter 5 Object Creation
- Introduction
- Item 33 Consider Factory Functions Instead Of Constructors
- Item 34 Consider A Primary Constructor With Named Optional Arguments
- Item 35 Consider Defining A DSL For Complex Object Creation
- Chapter 6 Class Design
- Introduction
- Item 36 Prefer Composition Over Inheritance
- Item 37 Use The Data Modifier To Represent A Bundle Of Data
- Item 38 Use Function Types Instead Of Interfaces To Pass Operations And Actions
- Item 39 Prefer Class Hierarchies To Tagged Classes
- Item 40 Respect The Contract Of Equals
- Item 41 Respect The Contract Of Hash Code
- Item 42 Respect The Contract Of Compare To
- Item 43 Consider Extracting Non Essential Parts Of Your API Into Extensions
- Item 44 Avoid Member Extensions
- Part 3 Efficiency
- Chapter 7 Make It Cheap
- Introduction
- Item 45 Avoid Unnecessary Object Creation
- Item 46 Use Inline Modifier For Functions With Parameters Of Functional Types
- Item 47 Consider Using Inline Classes
- Item 48 Eliminate Obsolete Object References
- Chapter 8 Efficient Collection Processing
- Introduction
- Item 49 Prefer Sequence For Big Collections With More Than One Processing Step
- Item 50 Limit The Number Of Operations
- Item 51 Consider Arrays With Primitives For Performance Critical Processing
- Item 52 Consider Using Mutable Collections
- Published with GitBook
第4条:不要把推断类型暴露给外部
第4条:不要把推断类型暴露给外部
Kotlin的类型推断是JVM中最流行的Kotlin特性之一。以至于Java 10也引入了类型推断(与Kotlin相比有限)。 不过,使用该特性也有一些危险性。最重要的是,我们需要记住,赋值的推断类型是右边的确切类型,而不是超类或接口类型:
open class Animal
class Zebra: Animal()
fun main() {
var animal = Zebra()
animal = Animal() // Error: Type mismatch
}
在大多数情况下,这都不是一个难题。当我们需要限定推断出的类型时,我们只需要指定它,问题就解决了:
open class Animal
class Zebra: Animal()
fun main() {
var animal: Animal = Zebra()
animal = Animal()
}
然而,当我们使用三方编写的一个库或另一个模块时,就没有这么容易了。在这种情况下,推断类型说明可能非常危险。让我们看一个例子。
假设你有以下接口用来代表汽车工厂:
interface CarFactory {
fun produce(): Car
}
如果没有指定其他参数,也会使用默认的类型Fiat126P
:
val DEFAULT_CAR: Car = Fiat126P()
因为绝大多数汽车工厂都可以生产它,所以你把它设为默认值。你没有给它声明返回值类型,因为你认为DEFAULT_CAR
无论如何都是Car
的实例:
interface CarFactory {
fun produce() = DEFAULT_CAR
}
类似地, 后来有其他人看到 DEFAULT_CAR
的声明并且认为它的类型能够被推断出来:
val DEFAULT_CAR = Fiat126P()
现在你会发现所有的工厂都只能生产Fiat126P
。这显然是有问题的。如果这个接口是你自己定义的,那么这个问题可能很快就会被发现并且很容易修复。但是,如果它作为外部API被提供给用户使用,你可能会从愤怒的用户那里得知这个问题。
除此之外,当某人不太了解API时,返回类型是很重要的信息。因此为了可读性,我们应该显式声明返回类型,特别是在我们的API的外部可见部分(即公开的API)中。
总结
一般的规则是,如果我们不确定返回值类型,我们应该显示声明它。这是很重要的信息,我们不应该把它隐藏起来 (Item 14: Specify the variable type when it is not clear)。此外,为了安全起见,在外部API中,我们应该始终指定类型。不能让它们随意改变。当我们的项目迭代时,推断类型可能会有很多限制或者很容易被更改。