scala 基础知识 FAQ
问题1: 抽象成员初始化规则
① 父类先初始化
② 在初始化的过程中,如果 val 发生重写,只有最后一个重写生效。前面的会变成零值,后面的会直接继承。
参考资料:https://docs.scala-lang.org/tutorials/FAQ/initialization-order.html
示例:
abstract class A { val x1: String val x2: String = "mom" println("A: " + x1 + ", " + x2) } class B extends A { val x1: String = "hello" println("B: " + x1 + ", " + x2) } class C extends B { override val x2: String = "dad" println("C: " + x1 + ", " + x2) } new C
输出:
A: null, null B: hello, null C: hello, dad
解析:
当一个 val 被重写时,只能初始化一次。例如,x2 在 B处初始化了,并且在 C处也初始化了,只有C处的生效。
如果 x2 同时在 B、C 两处初始化,打印的结果是
A: null, null B: hello, null C: hello, dad
如果 x2 仅在B处初始化则,打印的结果是
A: null, null B: hello, dad C: hello, dad
如果 x2不发生重写,初始值就是默认初始值。打印的结果是
A: null, mom B: hello, mom C: hello, mom
问题2: 偏函数
特性:
单参数的函数
不处理所有可能的输入,只处理那些能与至少一个 case 语句匹配的输入
可以用 isDefineAt 方法测试特定输入是否与偏函数匹配
偏函数之间可以链式连接
val pf1:PartialFunction[Any, String] = {case s:String => "YES"} val pf2:PartialFunction[Any, String] = {case d:Double => "YES"} val pf = pf1 orElse pf2 pf.isDefinedAt("d") // Boolean try { pf("d").toString } catch { case _:MatchError => "ERROR!" }
问题3:隐含参数
使用可以用最后一个参数列表来推断隐含参数。隐含参数是用 implicit 关键字声明的参数。
当相应方法被调用时,我们可以显式指定这个参数,或者也可以不指定,这时编译器会在当前作用域中找到一个合适的值作为参数。
隐含参数可以代替参数默认值,而且更加灵活。
示例:
import scala.concurrent.ExecutionContext.Implicits.global def sleep(millis: Long): Unit = { Thread.sleep(millis) } // Busy work ;) def doWork(index: Int) = { sleep((math.random * 1000).toLong) index } (1 to 5) foreach { index => val future = Future { doWork(index) } //定义事件回调。该方法接受两个参数列表。(pf: PartialFunction[T, U])(implicit executor: ExecutionContext) future onSuccess { case answer: Int => println(s"Success! returned: $answer") } future onFailure { case th: Throwable => println(s"FAILURE! returned: $th") } } sleep(1000) // Wait long enough for the "work" to finish. println("Finito!")
问题4:中缀表达式
中缀表达主要用于:操作符、类型声明、模式匹配
操作符
scala> val list = List() list: List[Nothing] = List() scala> "A" :: "B" :: list res4: List[String] = List(A, B)
类型声明
scala> class Foo[A,B] scala> val x: Int Foo String = null // Int Foo String 等同于 Foo[Int,String]
模式匹配
scala> case class Cons(a:String,b:String) defined class Cons scala> val x = Cons("one", "two") x: Cons = Cons(one,two) scala> x match { case "one" Cons "two" => println("ok") } ok // "one" Cons "two" 等同于 Cons("one", "two")
:: 在模式匹配指 case class,而不是方法
case head :: tail => …
233