SDKMAN
sdk install scala
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello, world!")
}
}
$ scalac HelloWorld.scala
$ scala HelloWorld.scala
Scala 特性
面向对象特性
Scala是一种纯面向对象的语言,每个值都是对象。对象的数据类型以及行为由类和特质描述。
类抽象机制的扩展有两种途径:一种途径是子类继承,另一种途径是灵活的混入机制。
这两种途径能避免多重继承的种种问题。
函数式编程
Scala也是一种函数式语言,其函数也能当成值来使用。
静态类型
Scala具备类型系统,通过编译时检查,保证代码的安全性和一致性。
并发性
Scala使用Actor作为其并发模型,Actor是类似线程的实体,通过邮箱发收消息。
Actor可以复用线程,因此可以在程序中可以使用数百万个Actor,而线程只能创建数千个。
在2.10之后的版本中,使用Akka作为其默认Actor实现。
#環境PATH設定
CALA_HOME:D:\Program Files(x86)\scala
Scala 与 Java 的最大区别是:Scala 语句末尾的分号 ; 是可选的。
scala
:help
:quit
交互式编程(pythonと同じ)
以"$"开头的标识符为保留的 Scala 编译器产生的标志符使用,应用程序应该避免使用"$"开始的标识符,以免造成冲突。
可以在"之间使用任何有效的 Scala 标志符,Scala 将它们解释为一个 Scala 标志符,一个典型的使用为 Thread 的 yield 方法, 在 Scala 中你不能使用 Thread.yield()是因为 yield 为 Scala 中的关键字, 你必须使用 Thread.`yield`()来使用这个方法。
forSome
implicit
lazy
sealed
trait
val
var
yield
-
:
=
=>
<-
<:
<%
>:
#
@
Scala是面向行的语言,语句可以用分号(;)结束或换行符。
定义包
第一种方法和 Java 一样
package com.runoob
class HelloWorld
第二种方法有些类似 C#,可以在一个文件中定义多个包。
package com.runoob {
class HelloWorld
}
import java.awt._ // 引入包内所有成员
import java.awt.{Color, Font}
// 重命名成员
import java.util.{HashMap => JavaHashMap}
// 隐藏成员
import java.util.{HashMap => _, _} // 引入了util包的所有成员,但是HashMap被隐藏了
注意:默认情况下,Scala 总会引入 java.lang._ 、 scala._ 和 Predef._,这里也能解释,为什么以scala开头的包,在使用时都是省去scala.的。
Any是所有其他类的超类
AnyRef类是Scala里所有引用类(reference class)的基类
上表中列出的数据类型都是对象,也就是说scala没有java中的原生类型。在scala是可以对数字等基础类型调用方法的。
符号字面量
符号字面量被写成: '<标识符>
如: 符号字面量 'x 是表达式 scala.Symbol("x") 的简写
Null类是null引用对象的类型,它是每个引用类(继承自AnyRef的类)的子类。Null不兼容值类型。
在 Scala 中,使用关键词 "var" 声明变量,使用关键词 "val" 声明常量。
声明变量实例如下:
var VariableName : DataType [= Initial Value]
var VariableName [: DataType] = Initial Value
var myVar : String = "Foo"
val myVal : String = "Too"
Scala 多个变量声明
val xmax, ymax = 100 // xmax, ymax都声明为100
val pa = (40,"Foo")
Scala 访问修饰符:private,protected,public(默认)
私有(Private)成员
用 private 关键字修饰,带有此标记的成员仅在包含了成员定义的类或对象内部可见,同样的规则还适用内部类。
保护(Protected)成员
因为它只允许保护成员在定义了该成员的的类的子类中被访问
作用域保护
Scala中,访问修饰符可以通过使用限定词强调。格式为:
private[x]
protected[x]
除了对x包中的类及它们的伴生对像可见外,对其它所有类都是private。
private[bobsrockets] class Navigator{
}
Scala 中使用 val 语句可以定义函数,def 语句定义方法。
class Test{
def m(x: Int) = x + 3
val f = (x: Int) => x + 3
}
var a = new Test()
a.f(3) # 6
a.m(7) # 10
???
方法声明http://www.runoob.com/scala/scala-functions.html
def functionName ([参数列表]) : [return type]
如果你不写等于号和方法主体,那么方法会被隐式声明为抽象(abstract),包含它的类型于是也是一个抽象类型。
方法定义
def functionName ([参数列表]) : [return type] = {
function body
return [expr]
}
如果方法没有返回值,可以返回为 Unit,这个类似于 Java 的 void
1.函数可作为一个参数传入到方法中,而方法不行。
2、在Scala中无法直接操作方法,如果要操作方法,必须先将其转换成函数。有两种方法可以将方法转换成函数:
val f1 = m _
在方法名称m后面紧跟一个空格和下划线告诉编译器将方法m转换成函数,而不是要调用这个方法。 也可以显示地告诉编译器需要将方法转换成函数:
val f1: (Int) => Int = m
new StringBuilder とnew StringBuilder()同じ
var myList = Array(1.9, 2.9, 3.4, 3.5)
// 输出所有数组元素
for ( x <- myList ) {
println( x )
}
// 计算数组所有元素的总和
var total = 0.0;
for ( i <- 0 to (myList.length - 1)) {
total += myList(i);
}
用 concat() 方法来合并两个数组:concat( myList1, myList2)
创建区间数组:var myList1 = range(10, 20, 2)
????Scala 数组方法
????Scala Iterator(迭代器)http://www.runoob.com/scala/scala-iterators.html
Scala 继承
1、重写一个非抽象方法必须使用override修饰符。
2、只有主构造函数才可以往基类的构造函数里写参数。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);
}
}
import java.io._
class Point(val xc: Int, val 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);
}
}
Scala 单例对象
在 Scala 中,是没有 static 这个东西的,但是它也为我们提供了单例模式的实现方法,那就是使用关键字 object。
Scala 中使用单例模式时,除了定义的类之外,还要定义一个同名的 object 对象,它和类的区别是,object对象不能带参数。
当单例对象与某个类共享同一个名称时,他被称作是这个类的伴生对象:companion object。你必须在同一个源文件里定义类和它的伴生对象。类被称为是这个单例对象的伴生类:companion class。类和它的伴生对象可以互相访问其私有成员。
Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大。
与接口不同的是,它还可以定义属性和方法的实现。所以其实 Scala Trait(特征)更像 Java 的抽象类。
一般情况下Scala的类只能够继承单一父类,但是如果是 Trait(特征) 的话就可以继承多个,从结果来看就是实现了多重继承。
Trait(特征) 定义的方式与类类似,但它使用的关键字是 trait,如下所示:
trait Equal {
def isEqual(x: Any): Boolean
def isNotEqual(x: Any): Boolean = !isEqual(x)
}
Scala 模式匹配
match 对应 Java 里的 switch,但是写在选择器表达式之后。即: 选择器 match {备选项}。
def matchTest(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case _ => "many"
}
match 表达式通过以代码编写的先后次序尝试每个模式来完成计算,只要发现有一个匹配的case,剩下的case不会继续匹配。
使用样例类
使用了case关键字的类定义就是就是样例类(case classes),样例类是种特殊的类,经过优化以用于模式匹配。
object Test {
def main(args: Array[String]) {
val alice = new Person("Alice", 25)
val bob = new Person("Bob", 32)
val charlie = new Person("Charlie", 32)
for (person <- List(alice, bob, charlie)) {
person match {
case Person("Alice", 25) => println("Hi Alice!")
case Person("Bob", 32) => println("Hi Bob!")
case Person(name, age) =>
println("Age: " + age + " year, name: " + name + "?")
}
}
}
// 样例类
case class Person(name: String, age: Int)
}
在声明样例类时,下面的过程自动发生了:
构造器的每个参数都成为val,除非显式被声明为var,但是并不推荐这么做;
在伴生对象中提供了apply方法,所以可以不使用new关键字就可构建对象;
提供unapply方法使模式匹配可以工作;
生成toString、equals、hashCode和copy方法,除非显示给出这些方法的定义。
[Scala 正则表达式](http://www.runoob.com/scala/scala-regular-expressions.html)
import scala.util.matching.Regex
object Test {
def main(args: Array[String]) {
val pattern = "Scala".r # String 类的 r() 方法构造了一个Regex对象
val str = "Scala is Scalable and cool"
println(pattern findFirstIn str)
}
}
捕获异常
import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException
object Test {
def main(args: Array[String]) {
try {
val f = new FileReader("input.txt")
} catch {
case ex: FileNotFoundException => {
println("Missing file exception")
}
case ex: IOException => {
println("IO Exception")
}
} finally {
println("Exiting finally...")
}
}
}
Scala 提取器(Extractor)
Scala 提取器是一个带有unapply方法的对象。
unapply方法算是apply方法的反向操作:unapply接受一个对象,然后从对象中提取值,
提取的值通常是用来构造该对象的值。
object Test {
def main(args: Array[String]) {
println ("Apply 方法 : " + apply("Zara", "gmail.com"));
println ("Unapply 方法 : " + unapply("[email protected]"));
println ("Unapply 方法 : " + unapply("Zara Ali"));
}
// 注入方法 (可选)
def apply(user: String, domain: String) = {
user +"@"+ domain
}
// 提取方法(必选)
def unapply(str: String): Option[(String, String)] = {
val parts = str split "@"
if (parts.length == 2){
Some(parts(0), parts(1))
}else{
None
}
}
}
以上对象定义了两个方法: apply 和 unapply 方法。通过 apply 方法我们无需使用 new 操作就可以创建对象。所以你可以通过语句 Test("Zara", "gmail.com") 来构造一个字符串 "[email protected]"。
提取器使用模式匹配
在我们实例化一个类的时,可以带上0个或者多个的参数,编译器在实例化的时会调用 apply 方法。我们可以在类和对象中都定义 apply 方法。
就像我们之前提到过的,unapply 用于提取我们指定查找的值,它与 apply 的操作相反。 当我们在提取器对象中使用 match 语句是,unapply 将自动执行,如下所示:
object Test {
def main(args: Array[String]) {
val x = Test(5)
println(x)
x match
{
case Test(num) => println(x + " 是 " + num + " 的两倍!")
//unapply 被调用
case _ => println("无法计算")
}
}
def apply(x: Int) = x*2
def unapply(z: Int): Option[Int] = if (z%2==0) Some(z/2) else None
}
执行以上代码,输出结果为:
$ scalac Test.scala
$ scala Test
10
10 是 5 的两倍!
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello, world!")
}
}
$ scalac HelloWorld.scala
$ scala HelloWorld.scala
Scala 特性
面向对象特性
Scala是一种纯面向对象的语言,每个值都是对象。对象的数据类型以及行为由类和特质描述。
类抽象机制的扩展有两种途径:一种途径是子类继承,另一种途径是灵活的混入机制。
这两种途径能避免多重继承的种种问题。
函数式编程
Scala也是一种函数式语言,其函数也能当成值来使用。
静态类型
Scala具备类型系统,通过编译时检查,保证代码的安全性和一致性。
并发性
Scala使用Actor作为其并发模型,Actor是类似线程的实体,通过邮箱发收消息。
Actor可以复用线程,因此可以在程序中可以使用数百万个Actor,而线程只能创建数千个。
在2.10之后的版本中,使用Akka作为其默认Actor实现。
#環境PATH設定
SCALA_HOME:D:\Program Files(x86)\scala