Scala 基础
简介
Scala 是一门基于 jvm 的多范式的编程语言,由 Martin Odersky 创建, 2003 年首次发布;
Scala设计的初衷是实现可伸缩 、并集成面向对象和函数式编程的各种特性;
Scala 平滑地集成面向对象和函数式语言的特点,并且 Scala 被编译在 Java 虚拟机上运行;
特性
面向对象:Scala 的每一个值都是一个对象,是纯面向对象语言,使用组合机制代替继承;
函数式:Scala 的每一个函数为一个值,提供了一个轻量级的语法用来定义匿名函数,支持高阶函数,它允许函数嵌套,并支持 curry 处理。
静态类型:
基于 JVM:Scala 可以使用在 Java SDK 的 Scala 中的所有类,也是自定义 Java 类或者 Java 开源项目;
语法
运算符
Scala 含有丰富的内置运算符,包括以下几种类型:
- 算术运算符:
+
、-
、*
、/
、%
- 关系运算符:
==
、!=
、>
、<
、>=
、<=
- 逻辑运算符:
&&
、||
、!
- 位运算符:
~
、&
、|
、^
、<<
、>>
、>>>
(无符号右移) - 赋值运算符:
=
数据类型
基本类型
Scala 中的基本类型和 Java 中的基本类型对应:
Java 基本类型 | Java 类 | Scala 类型 | 说明 |
---|---|---|---|
byte | Byte | Byte | -128~127 |
short | Short | Short | -32,768~32,767 |
int | Int | Int | -2,147,483,648~2,147,483,647 |
long | Long | Long | -9,223,372,036,854,775,808~9,223,372,036,854,775,807 |
float | Float | Float | IEEE 定义的 32 位浮点数 |
double | Double | Double | IEEE 定义的 64 位浮点数 |
char | Character | Char | 一个 Unicode 字符 |
boolean | Boolean | Boolean | true 或者 false |
特殊类型
Scala 中有几个特殊的类型:
Any
:任意类型,是所有类型的父类;AnyVal
:值类型,它的构造函数有一个参数,Scala 编译器对其做了一些特殊处理;AnyRef
:表示所有引用类型,也就是除了继承了AnyVal
的类以外的所有类的父类,类似于 Java 中的Object
;Unit
:无类型,类似于 Java 中的void
,但是在 Scala 中,可以定义 Unit 类型的变量。Unit
类型是单值类型(比较:Boolean
类型是双值类型,有true
和false
两个取值)。Nothing
:是所有类型的子类,基本上只用来作为泛型的参数。Null
是所有引用类型的子类,有一种值null
。
元组
元组的类型表示是用
()
包含的一系列类型,值是用()
包含的一系列表达式;长度为 1 的元组必须要用
Tuple1
声明;其他类型的元组都可以使用
()
表示;
|
|
变量
val
:常量,类似于 Java 中的 final 变量,一旦初始化之后,不可以重新赋值(我们可以称它为常变量)var
:变量,类似于一般的非 final 变量,可以任意重新赋值;
|
|
函数和方法
有函数和方法;
方法:使用
def
定义,一个具有名称和签名的类的一部分;函数:使用
val
定义,一个可以分配给变量的完整对象;使用
def
关键字定义;
|
|
类(class)
类由字段和方法组成;
字段保存对象的状态,并使用
val
或var
定义;方法完成对象的计算任务,并使用定义关键字
def
将
private
关键字添加到val
或var
字段,以防止 getter 和 setter 方法生成。
类构造函数
类的定义中可以有 1 个主构造函数, 多个辅助构造函数;
主构造函数和类名称定义在一起;
辅助构造函数通过 this 方法来定义;
如果构造函数参数声明为 val,只为它生成一个 getter 方法;
如果构造函数参数声明为 var,将生成访问器和 mutator 方法;
当在构造函数参数上未指定 val 和 var 时,不生成 getter 或 setter;
|
|
入口
主函数有两种启动方式:
继承
App
实现
main
函数
|
|
Object(伴生对象)
scala 的class没有static关键字概念, scala使用与类同名的object来封装class的静态属性和静态方法;
在Scala中,通过把变量放置在一个单例对象保管的方式,来实现Java的静态功能,这个专门保存单例对象的类在Scala中称之为伴生对象,它使用一个独立的
object
关键字来修饰,而非class
。伴生类和伴生对象必须存放在一个.scala文件中;
当同一个文件内同时存在
object x
和class x
的声明时:我们称
class x
称作object x
的伴生类。其
object x
称作class x
的伴生对象。其中伴生类和伴生对象需要同名。
类和伴生对象之间没有界限——它们可以互相访问彼此的private字段和private方法;
伴生对象中的属性可以直接使用类名进行调用;
伴生类中的属性,需要先实例化对象,才能够进行调用;
伴生对象特有的方法:apply。
没有class,只有object则是单例模式类;
object 中所有成员变量和方法默认都是 static 的;
伴生类
object x
被编译成了x.class
,伴生对象object x
被编译成了x$.class
;
|
|
apply
- apply()称为注入方法,是一个语法糖;
- 直接调用类(对象)名称时候,默认执行的是该类(对象)的apply()方法;
- 例如: Demo(“hello”) 实际调用的是 Demo.apply(“hello”), 因此 apply 方法又被称为注入方法;
- 目的是为了适应函数式编程的编码规范;
|
|
Case Class(样例类)
Case Class
(样例类)是一种特殊的类,能够被优化以用于模式匹配;类似于Java中的entity类,其属性不可变,且均为public;
Case Class
在比较的时候是按值比较而非按引用比较;
当一个类被声名为 case class 的时候,scala 会帮助我们做下面几件事情:
构造器中的参数默认的是 val 类型,除非显式声明为 var;
自动创建伴生对象,并实现
apply()
方法。可以不直接显示地 new 对象;伴生对象自动实现
unapply
方法,应用于模式匹配;实现自己的 toString、hashCode、copy、equals 方法;
对应所有构造参数,Scala 会自动定义对应的取值函数;
case class的实例可以借由模式匹配来拆解;
数据结构
Array
- 长度不可改变的数组;
|
|
ArrayBuffer
- 可变数组
|
|
Sealed(封闭)
sealed
关键字可以修饰class和trait;其修饰的 trait,class 只能在当前文件里面被继承;
在检查模式匹配的时候,用 sealed 修饰目的是让 scala 知道这些 case 的所有情况,scala 就能够在编译的时候进行检查,看你写的代码是否有没有漏掉什么没 case 到,减少编程的错误。
参考