Scala学习:为什么强调不可变对象?

Scala学习:为什么强调不可变对象?,第1张

scala中的不可变对象
  • 一、列表
  • 二、元组
  • 三、集合
  • 四、映射

Scala中提供了很多不可变的数据结构,包括列表(List)、集合(Set)、元组(Tuple)、映射(Map)等,而且推荐使用val来定义变量,为什么scala如此推崇不可变的对象呢?
scala不是一门纯函数式编程,它也允许指令式编程(类似Java、C++等),Scala编程一书中指出:函数式编程的重要理念之一就是不允许方法有副作用,一个方法要做的就是计算并返回一个值,个人认为一个函数只能通过参数来确定唯一值,方法外部定义一个非final变量(包括Java8后的lambda也是不允许使用非final变量的),某个方法对这个变量进行 *** 作,另一个方法也依赖这个变量,导致这两个方法产生了依赖关系,而不是仅通过参数来确定唯一值,换句话说,函数式编程中是提倡没有变量的
eg:

def printArgs(args:Array[String]):Unit = {
	var i = 0
	while (i < args.length){
		println(args(i))
		i += 1
	}
}
//这段代码是用来打印传入的参数,但明显是指令式风格的,改造成函数式风格如下:
def printArgs(args:Array[String]):Unit = {
	for (arg <- args){
		println(arg)
	}
}
但这还不是纯函数式风格的,因为有副作用(结果类型Unit表示不返回任何值,但这段代码的作用是向标准输出流打印)
def printArgs(args:Array[String]) = args.mkString("\n")
//mkString方法用于任何可被迭代访问的集合(数组、列表、集合映射等),返回对每个元素进行toString方法的字符串,括号中传入的是分隔符号,这段代码既没有var,也没有副作用,scala认为这才是真正的函数式编程
一、列表

scala创建不可变列表的方式(元素、长度都不可改变), *** 作列表的方法都是返回一个新对象列表

	val list1 = List(1,2,3)
	val list2 = List(4,5,6)
	val list3 = list1 ::: list2 //:::用于列表拼接
	val list4 = 1 :: list2 //::已有列表最前面添加一个新元素
	val list5 = Nil //定义一个空列表
	val list6 = 1 :: 2 :: 3 :: Nil //类似于List(1,2,3),注意结尾必须是Nil,因为1,2,3等Int对象没有::方法
	var list7 = List("li","shi")
	list7 = list7.::("ming")

可以发现成功拼接上了"ming",不是说列表是不可变的吗?
首先列表确实是不可变的,var/val其实是对象的地址引用,并不是对象本身,val修饰的地址引用不可变,var修饰的地址引用可变,和对象本身可变不可变并没有关系,这就类似于Java中的String,java中的string也是不可变的,如下代码所示

String s = new String("cheng")
String s1 = new String("ji")
s = s1
//这里的s也是指向了新的对象

而使用val修饰变量,对象的引用地址也不可改变,类似于java中的final,scala并不是纯函数式编程,个人认为scala允许使用var修饰变量是因为兼容指令式编程,不过提倡使用val来进行函数式编程

二、元组

scala中也提供的元组的不可变

val tuple1 = (99,"lishiming")
println(tupleq._1) //取出99
//上一章说过scala不是纯面向对象的吗?为什么元组没有apply方法像列表那样用List(0)圆括号包住小标取数据呢?
//列表和数组的apply方法都是针对同一种数据类型的,而元组包含了多种数据类型,_1可能是一种类型,_2可能又是另一种类型
三、集合

与列表不同,scala提供了可变与不可变的集合

	var set1 = Set("li","shi")
	set1 += "ming"
和列表一样,用var修饰集合,实际生成的是一个新的对象,用val修饰就不能添加元素了
集合还使用了真正可变的集合
	import scala.collection.mutable
	val set2 = mutable.Set("zhu","yuan")
	set2 += "zhang"
	//可以看到用val修饰的集合还可以添加数据
四、映射

scala也提供了可变与不可变的Map

不可变:
val map1 = Map(1 -> "li",2 -> "shi",3 -> "ming")
println(map1(1))
可变:
import scala.collection.mutable
val map2 = mutable.Map[Int,String](1 -> "li")
map2 += (2 -> "shi")
map2 += (3 -> "ming")
//可以在任何对象上调用->方法,它将返回一个键和值的元组(上篇说道scala万物皆对象,不了解1为何有->方法的可以看那篇文章)

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/736935.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-28
下一篇 2022-04-28

发表评论

登录后才能评论

评论列表(0条)

保存