Scala基本语法学习笔记
Scala语法与JAVA有很多相似的地方,两者也可以相互调用。但是整体感觉Scala语法等简洁、灵活。这里记录下Scala有特点的地方,以备以后查找方便。
参考:
使用 import:
Scala教程:
scala class和object,trait的区别:
scala中 object 和 class的区别:
1. import
1)基本语法跟JAVA相同:
import scala.io.StdIn
2)引用两个相同包下的类:
import java.io.{File, PrintWriter}
3)引用包下的所有类:
import java.io._ (相当于JAVA的import java.io.*)
4)排除(隐藏)引用:
import java.io.{Console=>_,_} (引用初java.io下除Console之外的所有类)
2. for循环比Java更灵活
1)标准for: i to j 语法(包含 j)
for( a <- 1 to 10 ) {
println("for[1 to 10] a: " + a)
}
println("---------------");
2)标准for: i until j 语法(不包含 j)
for( a <- 1 until 10 ) {
println("for[1 until 10] a: " + a)
}
println("---------------");
3)使用分号 (;) 来设置多个区间,它将迭代给定区间所有的可能值(相当于多重循环):
for( a <- 1 to 3; b <- 1 to 3 ) {
println("for[a;b] a: " + a + ", b: " + b)
}
println("---------------");
4)for集合: List 变量是一个集合,for 循环会迭代所有集合的元素
val numList = List(1,2,3,4,5,6)
for( a <- numList ) {
println("for[List] a: " + a)
}
println("---------------");
5)使用循环过滤,在for里加入if条件,多个条件用“;”隔开:
val numList2 = List(1,2,3,4,5,6,7,8,9,10)
for( a <- numList2
if a!=3; if a<8) {
println("for[List+filter] a: " + a)
}
println("---------------");
6)使用 yield:可以将 for 循环的返回值作为一个变量存储
val numList3 = List(1,2,3,4,5,6,7,8,9,10)
var retVal = for{ a <- numList3
if a!=3; if a<9
}yield a
for( a <- retVal ) {
println("for[List+filter+yield] a: " + a)
}
3. Option
Scala鼓励函数返回Option类型的值,有值则返回Some(),否则返回None
示例:
/**
* Scala Option(选项)类型用来表示一个值是可选的(有值或无值)。
* Option[T] 是一个类型为 T 的可选值的容器: 如果值存在, Option[T] 就是一个 Some[T] ,如果不存在, Option[T] 就是对象 None 。
* Option 有两个子类别,一个是 Some,一个是 None,当他回传 Some 的时候,代表这个函式成功地给了你一个 String,而你可以透过 get() 这个函式拿到那个 String,如果他返回的是 None,则代表没有字符串可以给你。
*/
object OptionTest {
def main(args: Array[String]): Unit = {
val sites = Map("runoob" -> "www.runoob.com", "google" -> "www.google.com")
println("sistes.get runoob : " + sites.get("runoob")) //get() 返回的是一个叫 Option[String] 的类别
println("sistes.get baidu : " + sites.get("baidu"))
println("------------")
//use match-case
println("show(sistes.get runoob) : " + show(sites.get("runoob"))) //get() 返回的是一个叫 Option[String] 的类别
println("show(sistes.get baidu) : " + show(sites.get("baidu")))
println("------------")
//use getOrElse
println("getOrElse(sistes.get runoob) : " + sites.get("runoob").getOrElse("there is no")) //get()不是None则返回value
println("getOrElse(sistes.get baidu) : " + sites.get("baidu").getOrElse("there is no")) //get()不到value则返回getOrElse传入作为默认值
println("------------")
//use isEmpty
println("isEmpty(sistes.get runoob) : " + sites.get("runoob").isEmpty) //返回false
println("isEmpty(sistes.get baidu) : " + sites.get("baidu").isEmpty) //返回true
println("------------")
}
def show(x: Option[String]) = x match {
case Some(s) => s
case None => "?"
}
}
输出结果:
sistes.get runoob : Some(www.runoob.com)
sistes.get baidu : None
------------
show(sistes.get runoob) : www.runoob.com
show(sistes.get baidu) : ?
------------
getOrElse(sistes.get runoob) : www.runoob.com
getOrElse(sistes.get baidu) : there is no
------------
isEmpty(sistes.get runoob) : false
isEmpty(sistes.get baidu) : true
------------
4. val 和 var
Scala有两种变量,val和var。
val不能再赋值,相当于JAVA的final
var可以被多次赋值。
5. 函数定义
1)函数声明
格式如下:
def functionName ([参数列表]) : [return type]
如果你不写等于号和方法主体,那么方法会被隐式声明为"抽象(abstract)",包含它的类型于是也是一个抽象类型。
2)函数定义
方法定义由一个def 关键字开始,紧接着是可选的参数列表,一个冒号":" 和方法的返回类型,一个等于号"=",最后是方法的主体。
格式如下:
def functionName ([参数列表]) : [return type] = {
function body
return [expr]
}
以上代码中 return type 可以是任意合法的 Scala 数据类型。参数列表中的参数可以使用逗号分隔。
如果函数没有返回值,可以返回为 Unit,这个类似于 Java 的 void。
3)main函数定义如下:
def main(args: Array[String]): Unit = {
println("hello world!"))
}
6. class、 object 和 trait
1)object
在scala中没有静态方法和静态字段,所以在scala中可以用object来实现这些功能,直接用对象名调用的方法都是采用这种实现方式,例如Array.toString。对象的构造器在第一次使用的时候会被调用,如果一个对象从未被使用,那么他的构造器也不会被执行;对象本质上拥有类(scala中)的所有特性,除此之外,object还可以一扩展类以及一个或者多个特质:例如,
abstract class ClassName(val parameter){}
object Test extends ClassName(val parameter){}
trait TraitA{}
trait TraitB{}
trait TraitC{}
object Test1 extends TraitA with TraitB with TraitC{}
注意:object不能提供构造器参数,也就是说object必须是无参的
我们通常会定义和使用object的apply方法,有如下情形,apply方法就会被调用,Object(参数1 ,参数2 ,……)这样是隐含的调用apply方法,当然也可以显示的调用,如下Array("Mary","tong"),当然也可以这样来写Array.apply("Mary","tong"),一般我们提倡隐式的写法。
所有的main方法都必须在object中被调用,来提供程序的主入口,十分简单,不举例说明,处理main方法以外,scala中还提供了扩展App特质,然后将程序代码放入都早起方法体内,如
object Hello extends App{
println("Hello World !!!")
}
这样的代码可以直接执行,输出
如果需要命令行参数,可以直接调用args属性来得到,例如
def main(args: Array[String]) {
if (args.length > 0 )
println("Hello " + args(0))
else
println("Hello World")
}
scala中并没有枚举类型,但是,标准类库中提供了一个枚举类型的接口,在object下面,可以扩展出枚举类型(Enumeration),
具体示例如下:
object EnumerationDemo extends Enumeration{
val red, green, blue, pink = Value
val black = Value // 上面一条语句是简写
val white = Value
val gray = Value
val yellow = Value(12, "huang") //可以随意指定id和名称,但是避免重复
val purple = Value("zi") //id为13
val orange = Value(20)
}
上面的代码为实现枚举类型的具体代码,如果不指定id和name,系统默认是id从0开始,name就是变量的名称,可以指定其中的
任何一个或者是两个全部指定,已经指定的就按指定的初始化,并且后面的依次递增。
枚举的引用
可以直接objectName.red这样来进行引用,也可以将import objectName._来进行导入引用,还可以给枚举类型增加一个类型别名,
具体如下:
object EnumerationDemo extends Enumeration{
type EnumerationDemo = Value
val red, green, blue, pink = Value
val black = Value
val white = Value
val gray = Value
val yellow = Value(12, "huang")
val purple = Value("zi")
val orange = Value(20)
}
现在枚举类型变成了EnumerationDemo.EnumerationDemo 这种用法只有在使用import语句的时候才显得有意义。
package enumeration
import EnumerationDemo._
/**
* Created by tongtong on 2015/9/8.
*
*/
class EnumDemo {
def transportation(color:Enumeration): Unit ={
if (color == red)
"Stop"
else if (color == green)
"go"
else if (color == yellow)
"wait"
}
}
枚举类型也可以通过for循环将所有元素输出,同时可以通过Enumeration(Int)和Enumeration.withName("")来进行
定位操作
2)class
在scala中,类名可以和对象名为同一个名字,该对象称为该类的伴生对象,类和伴生对象可以相互访问他们的私有属性,但是
他们必须在同一个源文件内。类只会被编译,不能直接被执行,类的申明和主构造器在一起被申明,在一个类中,主构造器只有一个,
所有必须在内部申明主构造器或者是其他申明主构造器的辅构造器,主构造器会执行类定义中的所有语句。scala对每个字段都会提供
getter和setter方法,同时也可以显示的申明,但是针对val类型,只提供getter方法,默认情况下,字段为公有类型,可以在setter
方法中增加限制条件来限定变量的变化范围,在scala中方法可以访问改类所有对象的私有字段
3)trait
在java中可以通过interface实现多重继承,在Scala中可以通过特征(trait)实现多重继承,不过与java不同的是,它可以定义自己的属性和实现方法体,在没有自己的实现方法体时可以认为它时java interface是等价的,在Scala中也是一般只能继承一个父类,可以通过多个with进行多重继承。