《Kotlin核心编程》 ——2.2.2 优先使用val来避免副作用

举报
华章计算机 发表于 2020/02/21 20:23:02 2020/02/21
【摘要】 本节书摘来自华章计算机《Kotlin核心编程》 —— 书中第2章,第2.2.2节,作者是水滴技术团队 。

2.2.2 优先使用val来避免副作用

在很多Kotlin的学习资料中,都会传递一个原则:优先使用val来声明变量。这相当正确,但更好的理解可以是:尽可能采用val、不可变对象及纯函数来设计程序。关于纯函数的概念,其实就是没有副作用的函数,具备引用透明性,我们会在第10章专门探讨这些概念。由于后续的内容我们会经常使用副作用来描述程序的设计,所以我们先大概了解一下什么是副作用。

简单来说,副作用就是修改了某处的某些东西,比方说:

修改了外部变量的值。

IO操作,如写数据到磁盘。

UI操作,如修改了一个按钮的可操作状态。

来看个实际的例子:我们先用var来声明一个变量a,然后在count函数内部对其进行自增操作。

var a = 1

fun count(x: Int) {

    a = a + 1

    println(x + a)

}

>>> count(1)

3

>>> count(1)

4

在以上代码中,我们会发现多次调用count(1)得到的结果并不相同,显然这是受到了外部变量 a 的影响,这个就是典型的副作用。如果我们把var换成val,然后再执行类似的操作,编译就会报错。

val a = 1

>>> a = a + 1

error: val cannot be ressigned

这就有效避免了之前的情况。当然,这并不意味着用val声明变量后就不能再对该变量进行赋值,事实上,Kotlin也支持我们在一开始不定义val变量的取值,随后再进行赋值。然而,因为引用不可变,val声明的变量只能被赋值一次,且在声明时不能省略变量类型,如下所示:

fun main(args: Array<String>) {

    val a: Int

    a = 1

    println(a) // 运行结果为 1

}

不难发现副作用的产生往往与可变数据及共享状态有关,有时候它会使得结果变得难以预测。比如,我们在采用多线程处理高并发的场景,“并发访问”就是一个明显的例子。然而,在Kotlin编程中,我们推荐优先使用val来声明一个本身不可变的变量,这在大部分情况下更具有优势:

这是一种防御性的编码思维模式,更加安全和可靠,因为变量的值永远不会在其他地方被修改(一些框架采用反射技术的情况除外);

不可变的变量意味着更加容易推理,越是复杂的业务逻辑,它的优势就越大。

回到在Java中进行多线程开发的例子,由于Java的变量默认都是可变的,状态共享使得开发工作很容易出错,不可变性则可以在很大程度上避免这一点。当然,我们说过,val只能确保变量引用的不可变,那如何保证引用对象的不可变性?你会在第6章关于只读集合的介绍中发现一种思路。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。