SCALA NOTES
具体类中变量必须初始化,只有 trait 和 abstract 类中的变量可以只声明类型不初始化
可以同时声明多个变量
val (x:Int, y:String) = (100, “Hello”)
val (x, y) = (100, “Hello”)
- 如果多个变量初始值相同,还可以
val x, y = 100
scala 语言层面中一切皆是对象,没有 java 中所谓的原生数据类型,当然虚拟机层面还是跟 java 一样。不需要包装类型、封包解包操作,这一切都是编译器的工作。
scala 底层用 java.lang.String 表示字符串,不过还通过 StringOps 追加了上百种操作。隐式转换
对于 Int, Double, Char 等也有 RichInt, RichDouble, RichChar,同样也有隐式转换
数值类型之间的转换用方法,而不是强制类型转换
无 ++, – 但是有 +=, -=,因为 Int 类型是不可变的
scala 无真正的操作符,操作符都是方法
不带参数且不改变当前对象的方法不带圆括号()
e.g. “Hello”.distinct使用伴生对象中的 apply 方法构建对象是常用的方法,可以看成 apply 方法实现 () 操作符,其实也是一个语法糖。
任何表达式都有值,包括if,for,赋值等。赋值语句的值为 Unit。
for 推导式的类型与 for 中第一个生成器的类型相同。
for(i<-0 to 10 if i%2==0; j<-9 to 19 if j+i >10) println(i, j) val t = for{ i<-0 to 10 if i%2==0 j<-9 to 19 if j+i >10} yield i+j
递归函数必须指明函数返回值类型
未命名参数与命名参数混用时,未命名参数放前面
默认参数赋值后置
带返回值的函数要写 =,无返回值的可不写或者写成 Unit
lazy 也有开销,每次访问都会有一个方法被调用,这个方法以线程安全的方式检查该值是否已经被初始化
没有受检异常,都是运行时异常
throw 表达式的类型是 Nothing,意味着 if/else 表达式的类型是另外一个分支的类型。
try {} catch {} finally {}
try {} catch {}
try {} finially {}
每个函数参数的类型都必须声明,即使相同类型也不能一起声明
e.g.def f(x: Int, y: Int)
函数参数都是 val 声明
伴生类和伴生对象必须放在同一个文件里
单例对象的伴生类不会影响虚构类中的内容
只有类可以带参数,object 和 trait 都不可以
快速编译指令
fsc -d class/ *.scala
fsc -shutdown
scala 作为脚本写时不能写在包里
scala 与 java 互操作库
scala.collection.JavaConversions._
scala.collection.JavaConverters._
包与源文件的当前路径无关,最好还是按包路径放置源文件,便于阅读;同一个源文件中可以定义多个互不包含的包;包的作用域只与源文件中包的定义相关。多个源文件可以给同一个包写内容,同一个源文件也可以给不同包写内容。
包对象对应的包可以直接访问包对象中的内容
为了避免包引用的错误引用,可以使用绝对包名。
e.g._root_.scala.collection.mutable.ArrayBuffer[String]
空包定义不会生成目录结构
重写非抽象成员加 override
字段重写规则
def 重写 def
val 重写 def
var 重写 抽象 var
var 重写 def getter & def setter字段setter & getter 重写定义
class Person(val name:String) { private var ageValue:Int = 0 def age = ageValue def age_=(newValue:Int) {ageValue = newValue} }
regex 最好用原始字符串形式定义,”“”…”“”.r,增强可读性
regex
正则提取器:
e.g.
val reg = """(\d+)(\w+?)""".r // 检查是否整个 Match val reg(t1, t2) = "123ok" // OK t1 = 123, t2 = ok val reg(t1, t2) = "t123ok" // scala.MatchError: val reg(t1, t2) = "123jdlaskfjl" // OK t1 = 123, t2 = jdlaskfjl, ?的作用弱化了 //提取满足条件的字串 for(reg(t1, t2) <- reg.findAllIn("this123ok234fdklj")) { println(t1, t2) } // 123 o // 234 f
所有的JAVA接口都可以当成是Trait
trait 中的具体字段是直接加到当前类中的,不是通过继承的方式得到的
带 return 语句的函数或者递归函数需要声明函数返回值类型
-柯里化是用当个参数函数实现多个参数函数的一种方法。在scala中柯里化函数后可以便于类型推断。
e.g. def f[T](a: Seq[T])(call: (T)=>String) = {...}
f("Hello")( _)
当第一个参数传入 “Hello”后,系统通过类型推断推出call的类型为 String => String,故可以直接写 ( _ ) 而不是 (_:String)
foreach 函数应用集合中的每个元素,只注重他的副作用而不是他的值。
flatMap 对返回的None值不处理,忽略
模式中可以带变量,包括match case, 变量声明以及for表达式;for推导式中不符合模式的匹配都会滤过
Option 可以看成是或者空或者带一个元素的集合
val t:Option[Int] = Some(100)
t.foreach(println)
case class 是针对模式匹配做了优化的类,会自动生成一些方法;case class 定义必须带(); 可以定义 case object
集合的 collect 方法对集合中在偏函数中有定义的值执行case对应的计算,并返回计算后的这些结果的集合
中缀表示法可以用以任何返回对偶(x,y)的unapply方法
f(x1, x2, x3, ...) = v
等同于f.update(x1, x2, x3, ..., v)
guard
case 语句只能加一个if守卫,for 语句可以加多个守卫PartialFunction 实例的 lift 方法可以使得其转化为一个值类型为Option的普通函数;一个输出值为 Option 的普通函数也可以通过 Function.lift 转化为一个 PartialFunction
FunctionN(N>1) 的对象可以通过 curried 柯里化函数;柯里化的函数也可以通过 Function.uncurried 函数转化为一个多参数函数。
PartialFunction 可以通过 orElse 方法进行组合
Function1 与 PartialFunction 才有 compose 和 andThen 方法
object 无泛型参数,class 与 trait 可以带泛型参数
case class 不能继承 case class
scala 只有两个命名空间
- 字段/方法/包/对象
- 类/特质