Scala是一个面向对象的函数式编程语言,在Scala中,一切皆函数。
函数式编程的优点:
- 提高生产效率,代码量更小。
- 更容易编写多并发或多进程的应用。
- 带来更少的bug,代码量小了,bug自然就小了。
Scala是一门基于JVM的静态语言,和Java能够无缝隙操作。尽管Scala是一门混合了面向对象编程和函数式编程的语言,但是它还是侧重于函数式编程。
Scala的安装
由于Scala是基于JVM的静态语言,所以安装Scala之前需要安装Java环境。安装步骤可以参考 【菜鸟教程】的链接:http://www.runoob.com/scala/scala-install.html
基础类型
这是要注意,Scala并没有基本数据类型,Scala的每一个基础类型都是一个类。在编译阶段,Scala编译器会自动将Scala基础类型转换为Java基本类型。
关键:Scala的基础类型的首字母都是大写的,如果写成小写会出现编译错误,这真是一个奇葩的特点。
变量
Scala有两种类型的变量:
- 可变变量,使用
var
定义。 - 不可变变量,使用
val
定义。
可变变量可以多次赋值:
var a=20
a=10
而不可变变量,初始化后不能再重新赋值:
val b=10
对于函数式编程,最好不要使用可变变量。
函数
在Scala中,函数和变量没有什么区别,它可以作为变量的值,可以在其他函数体中定义,可以作为函数的返回值,可以作为函数的参数。
Scala中用关键字def
来定义函数。
def add(a:Int, b:Int): Int={
val sum=a+b
return sum
}
add
是函数名;括号中的a
和b
是形参,Int
是形参类型;括号外的lnt
是函数返回值类型;接着一个=
号跟着大括号是函数体。
Scala中每条语句可以由分号;
结尾,也可以不写,当然不写是最方便的,怎么方便怎么来。
方法
方法是指类的成员函数,这一点和c++/Java类似。
局部函数
在其他函数或者方法中定义的函数称为局部函数,它只在其定义的函数内可见,即只有局部可见性。
高阶方法
把函数作为输入参数的方法称为高阶方法。类似的,高阶函数是指把函数作为参数的函数。
一个高阶函数的例子:
def encode(n: Int, f:(Int) => Long): Long ={
val x=n*10
f(x)
}
函数encode
接收两个参数,返回一个Long类型
的值。一个参数是Int
类型;另一个参数是函数f
,函数f
接收一个Int类型
的参数,返回的是Long类型
的值
函数字面量
函数字面量是指源代码中的匿名函数,它可以作为高阶方法或高阶函数的参数,也可以赋值给变量。
函数字面量的定义由处于圆括号中的输入函数列表、右箭头和函数体构成,下面是一个函数字面量的例子:
(x: Int) => {
x+100
}
闭包
闭包就是可以使用非局部变量的函数字面量。
类
类是面向对象编程的重要概念,是一组具有相同属性和行为的事物的抽象。Scala中的类和Java类似,它由字段和方法组成,字段就是属性,方法就是行为函数。
Scala使用关键字class
来定义一个类, 在Scala中的类没有访问控制这种操作,更为简洁:
class Car(mk: String, ml: String, cr: String){
val make=mk
val model=ml
var color=cr
def repaint(newColor: String) = {
color=newColor
}
}
类的实例使用关键字new
创建
val mustang=new Car("Ford", "Mustang", "Red")
因为Scala运行在JVM之上,所以不用显示删除对象,Java的垃圾回收器会自动删除那些不再使用的对象。
单例
在面向对象编程中一个常见的设计模式就是单例,它是指那些只可以实例化一次的类。Scala中使用关键字object
来定义单例对象
object DatabaseConnection{
def open(name: String) : Int ={
...
}
def read(streamId: Int) : Array[Byte] = {
...
}
def close(): Unit={
...
}
}
样本类
样本类是指使用case
修饰符的类,例如:
case class Message(from: String, to: String, content: String)
对于样本类,Scala提供了一些语法上的便利
- 不必使用关键字
new
就可以创建样本类的实例 - 样本类参数列表中的所有参数隐式获得
val
前缀 - 支持模式匹配
模式匹配
模式匹配是Scala中的概念,它类似于其他语言的switch语句
。考虑一个以颜色的字符串作为参数的简单函数:
def colorToNumber(color: String): Int ={
val num=color match{
case "Red" => 1
case "Blue"=> 2
case "Green"=> 3
case "Yellow" => 4
case _ =>0
}
return num
}
模式匹配的几个特性:
- Scala使用关键字
match
代替关键字switch
。 - 下划线代表默认选项。
- 每一个选项不需要
break语句
,匹配选项后,其他的选项不会被执行。 - 每一个选项对应一个表达式,每个表达式返回一个值。
操作符
Scala没有内置操作符,在Scala中,每个基础类型都是一个类,每一个操作符都是一个方法。使用操作符等价于调用方法。例如:
val a=10
val b=20
val c=a+b
这里的+
并不是Scala的内置操作符,它是定义在Int
类中的一个方法。Scala允许以操作符的方式来调用方法。
特征
Scala的特征类似于Java中的接口,然而,不同于Java接口,Scala的特征可以有方法的实现,而且它还可以有字段。
特征看上去像抽象类,它们都有字段和方法。区别在于一个类只能继承一个抽象类,但可以继承多个特征。
Scala中的特征使用关键字trait
定义:
trait Shape{
def area(): Int
}
class Square(length: Int) extends Shape{
def area=length*length
}
class Rectangle(length: Int, width: Int) extends Shape{
def area=length*width
}
val square = new Square(10)
val area = square.area
元组
元组是一个容器,用于存放多个不同类型的元素,它是不可变的。即创建元组之后,便不可修改。
元组是一个用小括号括起来的大杂烩:
val a=(10, true, "harry")
元组的下标从1开始的,访问元组的元素如下:
println(a._1)
println(a._2)
为什么下标数字前面有一个碍眼的下划线??鬼知道这种骚操作是为何。反正没下划线就会报错~
Option类型
Option是一种数据类型,用来表示值是可选的,即要么无值要么有值。它要么是样本类some
的实例,要么是单例对象None
的实例。
Option类型可以在函数或方法中作为值返回。返回some(x)
表示有值,返回None
表示无值。从函数返回的Option类型对象可以用于模式匹配中:
def colorCode(color: String): Option[Int] ={
color match{
case "Red" => Some(1)
case "Blue"=> Some(2)
case "Green"=> Some(3)
case "Yellow" => Some(4)
case _ => None
}
}
val code = colorCode("orange")
code match{
case Some(c) => println("code for orange is: " + c)
case None => println("code not defined for orange")
}
使用Option类型有助于避免空指针异常。
集合
集合是一种容器类的数据结构。Scala有丰富的集合类,集合类包含各种类型,所有的集合类都有同样的接口。
Scala的集合类可以分为三类:
- 序列
- 集合
- map
序列
序列表示有先后次序的元素序列,可根据位置来访问集合中的元素。
序列又分为三种:
- 数组
- 列表
- 向量
数组Array
数组是有索引的元素序列,所有的元素的数据类型相同,数组是可变的,可以修改元素但不能增加元素,即数组是定长的。
Scala中的数组类似于其他语言的数组,数组索引从0开始,通过索引访问或修改元素:
val arr = Array(10, 20, 30 ,40)
println(arr(0))
列表List
列表是一个线性的元素序列,存放一堆数据类型相同的元素,列表是不可变的,即创建后不可修改。
创建列表的几种方法:
val a=List(10, 20, 30)
val b=(1 to 100).toList
val c=someArray.toList
关于列表的几种操作:
- 访问第一个元素使用
head方法
。 - 访问第一个元素之后的所有元素使用
tail方法
。 - 判断列表是否为空,使用
isEmpty方法
。当列表为空时返回true
向量Vector
向量是结合了列表和数组的优点的类,根据索引访问元素占用固定的时间。向量支持快速修改和访问任意位置的元素:
val v1 = Vector(0, 10, 20, 30)
val v2 = v1 :+ 50 // 在向量末尾添加元素50
val v3 = v1(3)
集合Set
集合是一个无序的集合,且每个元素都不同,没用索引。
val f = Set(1, 2, 3 )
集合支持两种基本操作:
-
contains
: 如果集合中包含这个元素,则返回true
,并将这个元素作为参数传递过来 -
isEmpty
: 如果当前集合为空,则返回true
map
map是一个键-值对集合,在其他语言中,map也叫做字典。即根据键找出相应的值。
val a = Map("USA" -> "zhazha", "UK" -> "London", "India" -> "New Delhi")
val indiaCapital = a("India")
注意:Scala的各种集合类都是使用小括号,没有中括号和大括号!
集合类上的高阶方法
Scala集合的强大之处就在于这些高阶方法,这些高阶方法把函数当做参数。
map方法
map方法的参数是一个函数,它将这个函数作用于集合中的每一个元素,返回由其返回值所组成的集合。
val xs = List(1, 2, 3, 4)
val ys = xs.map((x: Int) => x*10.0)
println(ys)
输出如下:
scala> println(ys)
List(10.0, 20.0, 30.0, 40.0)
flatMap
Scala集合的flatMap方法类似于map,它的参数是一个函数,它把这个函数作用于集合中的每一个元素,返回另外一个集合。
val line = "Scala is fun"
val SingleSpace = " "
val words = line.split(SingleSpace)
val array = words.flatMap(_.toList)
array
输出结果为:
scala> array
res4: Array[Char] = Array(S, c, a, l, a, i, s, f, u, n)
Scala版的hello world
一个单独的Scala应用程序需要一个具有main方法
的单例对象。这个main方法
以一个Array[String]
类型的参数作为输入,它不需要返回值,它是这个Scala程序的入口,这个有main方法
的单例可以随便起名。
object HelloWorld{
/*
这是我的第一个Scala程序
*/
def main(args: Array[String]){
println("hello world!") // 输出hello world
}
}
Scala源代码文件以.scala
作为后缀名,依照惯例,一般以代码中的赖明或者单例名作为文件名,比如上面的代码文件应该命名为HelloWorld.scala
。
这篇文章写了一天,终于写完了。
每天学习一点点,每天进步一点点。