Kotlin学习之旅(D7)-Kotlin Idioms part 2

Kotlin学习之旅第七天

今天的主题是:Kotlin中的习惯用法-第二部分

前言

Kotlin学习之旅(D1)-学习计划&基本语法

Kotlin学习之旅(D2)-基本语法

Kotlin学习之旅(D3)-类与继承

Kotlin学习之旅(D4)-函数与Lambda表达式

Kotlin学习之旅(D5)-高级语法

Kotlin学习之旅(D6)-Kotlin Idioms part 1

今日目标

  • 使用表达式
  • 静态方法
  • 使用命名参数替代setter
  • 使用apply()
  • 处理可空对象
  • 使用as替代is
  • 快速创建JSON

使用表达式

通过使用Lambda表达式,我们可以减少很多的代码量,同时也会牺牲可读性,但是我们还是鼓励使用表达式

举个栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
fun getDefaultLocale(deliveryArea: String): Locale {
val deliverAreaLower = deliveryArea.toLowerCase()
if (deliverAreaLower == "germany" || deliverAreaLower == "austria") {
return Locale.GERMAN
}
if (deliverAreaLower == "usa" || deliverAreaLower == "great britain") {
return Locale.ENGLISH
}
if (deliverAreaLower == "france") {
return Locale.FRENCH
}
return Locale.ENGLISH
}

这个函数的目的是为了获取正确的地区,在函数体中做了很多的判断,每一个需要接手的人都要重新过一遍逻辑,但是由于大量的if,读一遍代码的速度会变慢,时间自然就会变长,那么使用表达式的效果是怎么样的呢?

1
2
3
4
5
6
fun getDefaultLocale2(deliveryArea: String) = when (deliveryArea.toLowerCase()) {
"germany", "austria" -> Locale.GERMAN
"usa", "great britain" -> Locale.ENGLISH
"france" -> Locale.FRENCH
else -> Locale.ENGLISH
}

没错,只要6行,就能达到和上面13行代码一样的效果,并且可读性上面我觉得还提升了。因为人的大脑是习惯有关联的东西,when表达式其实就是把并列的条件一个个列出来,对于读代码的人来说是很好理解的。

因此,考虑多使用 when 而不是if

静态方法

在Kotlin里面,没有提供static关键字让我们定义静态的变量,方法,类,但是我们可以通过别的方式来实现

1.通过Object关键字

1
2
3
object MyUtil {
fun changeAnswer(string: String) : Int { ... }
}

使用:

1
MyUtil.changeAnswer("test")

2.通过扩展函数

这个在昨天的 Kotlin学习之旅(D6)-Kotlin Idioms part 1 已经讲过了,所以这里就不再重复了。

使用命名参数替代setter

在Java里面,我们通过setXXX这样的命名方法来区分每个参数

1
2
3
4
5
val config = SearchConfig()
.setRoot("~/folder")
.setTerm("kotlin")
.setRecursive(true)
.setFollowSymlinks(true)

在Kotlin里面,我们通过直接给参数命名~

1
2
3
4
5
6
val config2 = SearchConfig2(
root = "~/folder",
term = "kotlin",
recursive = true,
followSymlinks = true
)

简洁又明了:参数名 = "参数值"

使用apply()

这个用法和上面的差不多

1
2
3
4
5
6
7
8
val dataSource = BasicDataSource()
dataSource.driverClassName = "com.mysql.jdbc.Driver"
dataSource.url = "jdbc:mysql://domain:3309/db"
dataSource.username = "username"
dataSource.password = "password"
dataSource.maxTotal = 40
dataSource.maxIdle = 40
dataSource.minIdle = 4

常规操作是这样的,那么Kotlin有什么骚操作呢?

1
2
3
4
5
6
7
8
9
val dataSource = BasicDataSource().apply {
driverClassName = "com.mysql.jdbc.Driver"
url = "jdbc:mysql://domain:3309/db"
username = "username"
password = "password"
maxTotal = 40
maxIdle = 40
minIdle = 4
}

同样的道理,通过apply() 后面也是 参数名 = "参数值" 就搞定了

处理可空对象

大家都知道,Kotlin默认是空安全的,但是也支持可空对象,那么如果对象是可为空的,在使用的时候我们就需要判断是否为空

1
2
3
4
if (order == null || order.customer == null || order.customer.address == null){
throw IllegalArgumentException("Invalid Order")
}
val city = order.customer.address.city

这是很常见的一种写法,但是如果大量使用,特别是在解析JSON的时候,就会让人觉得做了大量重复的工作,在Kotlin中,我们鼓励用这种写法:

1
val city = order?.customer?.address?.city ?: throw IllegalArgumentException("Invalid Order")

通过 ? 来判断是否为空,如果为空会直接抛出异常,避免写大量的ifxxx == null

使用as替代is

同样的,我们在kotlin里面常用的判断还有 is

1
2
3
4
if (service !is CustomerService) {
throw IllegalArgumentException("No CustomerService")
}
service.getCustomer()

在这里我们可以通过as 来替换

1
2
service as? CustomerService ?: throw IllegalArgumentException("No CustomerService")
service.getCustomer()

反正出发点就是减少if语句的使用,提高代码的可读性,顺便还能减少代码量

快速创建JSON

这个功能也是非常有用的,毕竟写单元测试的时候需要模拟测试数据~

1
2
3
4
5
6
7
8
9
10
val customer = mapOf(
"name" to "Clair Grube",
"age" to 30,
"languages" to listOf("german", "english"),
"address" to mapOf(
"city" to "Leipzig",
"street" to "Karl-Liebknecht-Straße 1",
"zipCode" to "04107"
)
)

通过 参数名 to 参数值 这样的形式来创建JSON,不仅仅是String,Int等常用的数据类型,包括map,list都可以创建,是不是很方便呢?

总结

在Day 6 和 Day 7 里面我们总结了一些Kotlin的习惯用法,多加练习,掌握这些用法可以提高我们的开发效率,并且促使我们写出好的代码。

接下里就要进入到Java to Kotlin 的学习里面啦,其实经过了前面Kotlin的语法,用法的学习,对于Kotlin这门语言的常用知识点都了解得差不多了,加油💪

Day 7 - Learn Kotlin Trip, Completed.


本文结束啦感谢您的阅读