Scala简介
Scala 是一种现代多范式编程语言,它平滑地集成了面向对象语言和函数式语言的特性。 Scala运行在Java平台(JVM,Java虚拟机)上,并且与现有的Java程序兼容。 Scala 代码可以调用 Java 方法、访问 Java 字段、继承 Java 类和实现 Java 接口。在面向对象编程方面,Scala是一种非常纯粹的面向对象编程语言。
Scala安装
Scala需要安装相应的编程环境。 Scala程序需要运行在JVM(Java虚拟机)上。因此,在安装Scala之前,需要先在Windows系统中安装Java,然后再安装Scala。
斯卡拉官方网站下安装镜像
bin
下的scala.bat
是交互窗口
你可以选择交互窗口来练习语法,当然也可以配置环境变量以方便后续使用IDE。
Scala基于jvm运行,因此也可以安装相应的插件在java的集成开发环境中使用。我们推荐与 Eclipse 结合的 IDE。
http://scala-ide.org/download/sdk.html
下载后是一个压缩包
解压后直接打开eclipse.exe就可以使用
Linux系统安装
sudo apt-get install openjdk-7-jre openjdk-7-jdk
安装jdk后,需要配置环境变量。
将下载的scala上传到系统:
解压scala文件:
配置scala的环境变量:
vim /etc/profile
source /etc/profile
重启环境变量。
输入scala
验证是否安装成功:
quit
退出scala
Scala特性
支持的编程范例
Scala是一种纯面向对象的语言,每个值都是对象。对象的数据类型以及行为由类和特质描述。类抽象机制的扩展有两种途径。一种途径是子类继承,另一种途径是灵活的混入机制。这两种途径能避免多重继承的种种问题。
函数式编程
Scala也是一种函数式语言,其函数也能当成值来使用。Scala提供了轻量级的语法用以定义匿名函数,支持高阶函数,允许嵌套多层函数,并支持柯里化。Scala的case class及其内置的模式匹配相当于函数式编程语言中常用的代数类型。
静态类型
Scala 有一个类型系统,可以通过编译时检查确保代码安全性和一致性。该类型系统具体支持以下功能:
-
通用类别,
-
协变和逆变,
-
标签,
-
类型参数的上限和下限约束,
-
将类别和抽象类型视为对象成员,
-
复合型、
-
引用自己时明确指定类型,
-
看法,
-
多态性方法。
Scala数据类型
安装Scala后,编写第一个hello world程序。在Scala中,必须使用对象方法
object HelloWorld {
def main(args: Array[String]){
println("Hello, World!")
}
}
在scala中scalac
是编译,scala
是运行,和java类似也会产生.class
文件(也可以交互式运行)
scala的基本语法:
Scala的基本语法需要注意以下几点:
-
区分大小写 - Scala 区分大小写,这意味着标识符 Hello 和 hello 在 Scala 中将具有不同的含义。
-
类名 - 所有类名的首字母大写。如果需要使用多个单词组成类名,请将每个单词的第一个字母大写。示例:MyFirstScalaClass 类
-
方法名称 - 所有方法名称的第一个字母都是小写的。如果方法名称由多个单词组成,则每个单词的首字母应大写。示例:def myMethodName()
-
程序文件名 - 程序文件的名称应与对象名称完全匹配(新版本中不再需要,但建议保持此习惯)。保存文件时,应使用对象名称保存它(记住 Scala 区分大小写)并附加“.scala”作为文件扩展名。 (如果文件名和对象名不匹配,程序将无法编译)。示例:假设“HelloWorld”是对象的名称。然后该文件应保存为“HelloWorld.scala”
-
def main(args: Array[String]) - Scala 程序处理从 main() 方法开始,这是每个 Scala 程序的强制程序入口部分。
Scala 注释
object HelloWorld {
/* * * 多行注释 */
def main(args: Array[String]) {
// 输出 Hello World
// 这是一个单行注释
println("Hello, world!")
}
}
空行和空格
如果一行仅包含空格或注释,Scala 会将其视为空行并忽略它。标签可以用空格或注释分隔。
val s = "php中文网"; println(s)
Scala 包
定义包
Scala 使用 package 关键字定义包,在Scala将代码定义到某个包中有两种方式:
第一种方法和Java一样,在文件头中定义包名。在该方法中,所有后续代码都放在包中。例如:
package com.php
class HelloWorld
第二种方法有点类似于C#。第二种方法可以在一个文件中定义多个包。
package com.php {
class HelloWorld
}
参考包
Scala 使用 import 关键字引用包。
import java.awt.Color // 引入Color
import java.awt._ // 引入包内所有成员
def handler(evt: event.ActionEvent) {
// java.awt.event.ActionEvent
... // 因为引入了java.awt,所以可以省去前面的部分
}
导入语句可以出现在任何地方,而不仅仅是出现在文件的顶部。 import 的效果从语句块的开头延伸到结尾。这大大减少了名称冲突的可能性。
import java.awt.{
Color, Font}
// 重命名成员
import java.util.{
HashMap => JavaHashMap}
// 隐藏成员
import java.util.{
HashMap => _, _} // 引入了util包的所有成员,但是HashMap被隐藏了
如果你想从包中引入多个成员,你可以使用选择器:
换行符
Scala是面向行的语言,语句可以用分号;
结束或换行符。Scala 程序里,语句末尾的分号通常是可选的。
Scala有两种类型的变量,一种是val,它是不可变的,声明时必须初始化,初始化后不能赋值;另一个是var,它是变量,需要在声明Initialized时初始化,初始化后可以再次赋值。
Scala 数据类型
Scala 具有与 Java 相同的数据类型。下表列出了 Scala 支持的数据类型:
上表中列出的数据类型都是对象,也就是说scala没有类似java中的基本数据类型。在scala是对数字等基础类型调用方法的。
Scala 基础字面量
整数文字:整数文字用于 Int 类型。如果代表Long,可以在数字后添加L或小写l作为后缀。字节和短不是必需的。
浮点文字:默认为 Double 类型。如果是Float,则需要后面加f或F后缀。
布尔文字:布尔文字包括 true 和 false。
字符字面量:在scala中字符类型表示为半角单引号(')中的字符。其中 \
表示转移字符。
字符串字面量:字符串表示方法是在双引号中"
包含一系列字符 。
多行字符串的表示方法:多行字符串用三个双引号来表示分隔符,格式为:""" ... """
。
Null 值:Null 值是 scala.Null 类型。 Scala.Null 和 scala.Nothing 是特殊类型,它们以统一的方式处理 Scala 面向对象类型系统的某些“边缘情况”。
Null 类是空引用对象的类型,它是每个引用类(继承自 AnyRef 的类)的子类。 Null 是不兼容的值类型。
Scala 变量
变量是一个方便的占位符,用于引用计算机内存地址。变量创建后,会占用一定的内存空间。
根据变量的数据类型,操作系统将分配内存并决定在保留内存中存储什么内容。因此,通过为变量分配不同的数据类型,您可以在这些变量中存储整数、小数或字母。
变量声明
一、变量: 在程序运行过程中其值可能发生改变的量叫做变量。
二、常量 在程序运行过程中其值不会发生变化的量叫做常量。
在 Scala 中,使用关键词 var
声明变量,使用关键词 “val” 声明常量。
var name : String = "CSDN"
val website : String = "www.csdn.net"
变量类型声明
变量的类型在变量名之后、等号之前声明。定义变量类型的语法如下:
var name : String = "CSDN"
在 Scala 中声明变量和常量时无需指定数据类型。如果未指定数据类型,则从变量或常量的初始值推断数据类型。
var myVar = 10;
val myVal = "Hello, Scala!";
因此,如果声明变量或常量时未指定数据类型,则必须给出其初始值。
这种声明方式和js类似,都是类型化语言。
Scala 多变量声明
Scala 支持多个变量的声明:
val xmax, ymax = 100 // xmax, ymax都声明为100
如果方法返回值是元组,我们可以使用 val 来声明一个元组:
val (myVar1: Int, myVar2: String) = Pair(40, "Foo")
也可以不指定数据类型:
val (myVar1, myVar2) = Pair(40, "Foo")
scala具有类型推断的能力,也可以显示定义变量。(这点和js有点像,分配内存空间)
Scala 访问修饰符
Scala 访问修饰符与 Java 基本相同,包括:private、protected 和 public。
如果未指定访问修饰符,则 Scala 对象的访问级别默认为 public。
Scala 中的 private 限定符比 Java 更严格。对于嵌套类,外部类甚至无法访问嵌套类的私有成员。
Scala 运算符
与Java基本相同。
Scala循环和条件语句
与Java基本相同。
Scala 函数
函数声明
函数声明通过关键字def
。方法定义由一个def 关键字开始,紧接着是可选的参数列表,一个冒号":" 和方法的返回类型,一个等于号"=",最后是方法的主体。Scala 函数定义格式如下:
def functionName ([参数列表]) : [return type] = {
function body
return [expr]
}
如果函数没有返回值,可以返回为 Unit,这个类似于 Java 的 void。
如果没有等于号和方法主体,那么方法会被隐式声明为"抽象(abstract)",包含它的类型于是也是一个抽象类型。
函数调用
通过方法名调用:
object MethodTest {
def main(args : Array[String]){
var a:Int =0
a =add(1,3)
print(a)
}
def add(a:Int,b:Int) : Int={
var c:Int = 0
c=a+b
return c
}
}
通过类的实例对象调用:
object Method1 {
def method1():Unit={
print("method1")
}
}
object MethodTest {
def main(args : Array[String]){
//实例化对象
var meth1=
Method1.method1()
}
语法与js一致。不需要像Java那样通过new关键字直接引用实例对象。
Scala的基本数据类型与Java类似。
println
用于打印具有换行效果,printf
也用于打印有C语言风格的格式化字符串的效果。
要在scala中写入文件,您需要使用java.io.PrintWriter将数据写入文本文件。
scala> import java.io.PrintWriter
import java.io.PrintWriter //这行是Scala解释器执行上面语句后返回的结果
scala> val out = new PrintWriter("output.txt")
out: java.io.PrintWriter = java.io.PrintWriter@25641d39 //这行是Scala解释器执行上面语句后返回的结果
scala> for (i <- 1 to 5) out.println(i)
scala> out.close()
查看写入的文件:
Scala 读取文件并使用 Scala.io.Source 的 getLines 方法读取文件中的所有行。
scala> import scala.io.Source
import scala.io.Source //这行是Scala解释器执行上面语句后返回的结果
scala> val inputFile = Source.fromFile("output.txt")
inputFile: scala.io.BufferedSource = non-empty iterator //这行是Scala解释器执行上面语句后返回的结果
scala> val lines = inputFile.getLines //返回的结果是一个迭代器
lines: Iterator[String] = non-empty iterator //这行是Scala解释器执行上面语句后返回的结果
scala> for (line <- lines) println(line)
1
2
3
4
5
条件语句
val x = 6
if (x>0) {
println("This is a positive number")
} else {
println("This is not a positive number")
}
val x = 3
if (x>0) {
println("This is a positive number")
} else if (x==0) {
println("This is a zero")
} else {
println("This is a negative number")
}
循环语句
//while循环
var i = 9
while (i > 0) {
i -= 1
printf("i is %d\n",i)
}
var i = 0
do {
i += 1
println(i)
}while (i<5)
for循环语句格式如下:
for (变量<-表达式) 语句块
其中,“变量<-表达式”被称为“生成器(generator)”
for (i <- 1 to 5) println(i)
for (i <- 1 to 5 by 2) println(i)
Scala数据结构,数组是编程中经常使用的数据结构,一般包括定长数组和变长数组。
val intValueArr = new Array[Int](3) //声明一个长度为3的整型数组,每个数组元素初始化为0
intValueArr(0) = 12 //给第1个数组元素赋值为12
intValueArr(1) = 45 //给第2个数组元素赋值为45
intValueArr(2) = 33 //给第3个数组元素赋值为33
val intValueArr = Array(12,45,33)
val myStrArr = Array("BigData","Hadoop","Spark")
Scala 也有列表和元组的概念。
类和对象是Java、C++等面向对象编程的基本概念。类是用于创建对象的蓝图。定义好类后,就可以使用new关键字来创建对象了。
class Counter{
//这里定义类的字段和方法
}
然后,就可以使用new关键字来生成对象:
new Counter //或者new Counter()
//给类增加字段和方法
class Counter {
private var value = 0
def increment(): Unit = {
value += 1}
def current(): Int = {
value}
}
Scala数组
数组声明
var z:Array[String] = new Array[String](3)
或
var z = new Array[String](3)
数组的使用与Java中基本相同
Scala类
类是对象的抽象,对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。类是创建对象的蓝图,是定义特定类型对象中包含的方法和变量的软件模板。
class Point(xc: Int, yc: Int) {
var x: Int = xc
var y: Int = yc
def move(dx: Int, dy: Int) {
x = x + dx
y = y + dy
println ("x 的坐标点: " + x);
println ("y 的坐标点: " + y);
}
}
class Location(override val xc: Int, override val yc: Int,
val zc :Int) extends Point(xc, yc){
var z: Int = zc
def move(dx: Int, dy: Int, dz: Int) {
x = x + dx
y = y + dy
z = z + dz
println ("x 的坐标点 : " + x);
println ("y 的坐标点 : " + y);
println ("z 的坐标点 : " + z);
}
}
override val xc 覆盖父类的字段。
继承会继承父类的所有属性和方法。 Scala只允许继承一个父类。
object
Scala 中定义对象有三种方式:对象、类和特征。
在Java中,一个类可以实例化多个对象。 Scala 有一个很大的区别:
object
:单例对象概念
Scala 具有直接创建对象的能力,该对象无需类即可定义其成员。不需要 new,就能直接创建一个对象。而且创建对象的方式和定义类的方式是一样的,唯一的区别就是创建对象要使用 object 关键字。通过 object 直接创建的对象,我们称为单例对象
。 单例对象是没有类就可以存在的对象,这样的对象是独一无二的,不像通过 class 方式可以 new 无数的对象。
那么为什么Scala中的程序入口main()方法必须在object创建的单例对象中执行,而不是像Java那样呢?
许多面向对象的编程语言包括 Java 都是使用
static
关键字修饰 main() 方法,这样 main() 方法就变成了类静态方法,这样在类加载完成后就可以直接调用 main() 方法了。但是,Scala 根本就没有 static 关键字, 也没有类静态方法和静态属性。这就是为什么在 Scala 中 main() 方法只能放在 object 定义的单例对象中执行。
伴生对象和伴生类
如果类和单例对象具有相同的名称,则该类是该对象的伴生类,该对象是该类的伴生对象。
伴生对象和伴生类在Scala的面向对象编程方法中占有极其重要的地位。它们主要用来替代Java静态成员变量和静态方法。许多 Scala 工具方法是使用单例对象或伴生对象实现的。
伴生类和伴生对象可以访问彼此的私有属性或方法,但它们必须位于同一个源文件中。
class companion{
var a = 23;
var b = 78;
def sum(){
println("The sum is: "+ (a+b));
}
}
object companion{
def main(args:Array[String]){
new companion().sum();
}
}
class
Scala 是一种面向对象的编程语言,因此它定义和使用类的方式与 Java 基本相同,但与 Scala 存在一些差异。 Scala 中有新概念:主构造函数、辅助构造函数和私有构造函数。大致意思就是构造方法和方法重载发生了一些变化。构造方法可以用this关键字代替,可以私有化。
trait
在 Scala 中,trait 相当于 Java 接口。与接口不同的是,它还可以定义属性和方法的实现,这更像是Java抽象类。如果你有一个特质(feature),你可以继承多个,结果就是实现了多重继承。
Scala Collection
// 定义整型 List
val x = List(1,2,3,4)
// 定义 Set
var x = Set(1,3,5,7)
// 定义 Map
val x = Map("one" -> 1, "two" -> 2, "three" -> 3)
// 创建两个不同类型元素的元组
val x = (10, "php")
// 定义 Option
val x:Option[Int] = Some(5)
Scala 模式匹配
match
关键字对应 Java 里的 switch,但是写在选择器表达式之后。即: 选择器 match {备选项}。
object Test {
def main(args: Array[String]) {
println(matchTest(3))
}
def matchTest(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case _ => "many"
}
}
通过按照代码编写顺序尝试每个模式来评估匹配表达式。只要找到匹配的案例,剩余的案例就不再继续匹配。
Scala 异常处理
与Java相同。
Scala提取器
Scala 文件 I/O
与Java相同。