了解Java Lambda表达式
函数式接口
一种只含有一个抽象方法声明的接口
可以使用匿名内部类来实例化函数式接口的对象
通过Lambda表达式可以进一步简化代码
Lambda语法
(parameters) -> expression
(parameters) ->{ statements;...... }
掌握Scala函数编写
函数式编程:函数是Scala的核心
方法是类的一部分,属于定义在类中的函数
函数定义
def 函数名([参数列表])[:返回类型]={
函数体
[return] 表达式
}
//匿名函数定义
(参数列表)=>{函数体}
函数调用
函数名(参数列表)
//定义一个函数/方法
def square(x: Int): Int = {
println(x)
return x * x //return可省略
}
Val f0=square _
//定义一个函数方式2
val f1 = (x:Int,y:Int) => x + y
掌握Scala高阶函数用法
高阶函数可以将其他函数作为参数或者使用函数作为输出结果
常用高阶函数
map
foreach
filter
fold、foldLeft、foldRight
reduce
zip
flatten
flatMap
//函数作为参数
def doSquare(f:Int=>Int,p:Int)=f(p)
def square(x:Int):Int=x*x
doSquare(square,square(2))
//函数作为返回值
//返回类型为函数(Int=>Int)
def doSquare()={
(x:Int)=>x*x
}
doSquare()(2)
理解Scala隐式操作原理
方法可以具有隐式参数列表,由参数列表开头的implicit 关键字标记
implict只能修改最尾部的参数列表,应用于其全部参数
Scala可自动传递正确类型的隐式值
通常与柯里化函数结合使用
def sum(x:Int)(implicit y:Int)=x+y
implicit var a=10 //将作为Int类型隐式值自动传递
sum(10) //20
理解闭包的概念
闭包是依照包含自由变量的函数字面量在运行时创建的函数值
闭包是对函数本身及其所使用的自由变量的统一定义
var y=1
val add=(x:Int)=>x+y //add是闭包,y是自由变量
闭包的变量绑定
闭包可捕获自由变量的变化
闭包对捕获变量作出的改变在闭包之外也可见
掌握Scala面向对象基本特性
类(class)
类通过class关键字定义
类通过new关键字创建实例
类拥有成员变量和方法
类的成员默认为public,也支持private、protected
类中无法定义静态成员变量和方法
类无需明确定义构造方法,通过构造参数列表声明为类的一部分
类成员访问修饰符
Java
Modifier | Class | Package | Subclass | World |
---|---|---|---|---|
public | Y | Y | Y | Y |
protected | Y | Y | Y | N |
default | Y | Y | N | N |
private | Y | N | N | N |
Scala
Modifier | Class | Companion | Subclass | Package | World |
---|---|---|---|---|---|
default(public) | Y | Y | Y | Y | Y |
protected | Y | Y | Y | N | N |
private | Y | Y | N | N | N |
类的定义
构造器
主构造器
辅助构造器
成员变量与方法
类的实例化
var p=new Point()
p.x
p.y
p=new Point(12,11)
p.x
p.y
p.move(1,2)
//主构造器的参数列表直接定义在类名后面
class Point(xc: Int, yc: Int) {
var x: Int = xc //成员变量
var y: Int = yc
//辅助构造器
def this() ={
this(0, 0) //第一句必须调用其他构造器
}
//成员方法
def move(dx: Int, dy: Int) ={
x = x + dx
y = y + dy
}
}
类的继承
Scala使用“extends”关键字实现继承
子类重写父类方法必须使用“override”关键字
class BlackPoint() extends Point {
private var color="black"
override def move(dx: Int, dy: Int) ={
x = x + dx
y = y + dy
println("moved to x:"+x+" y:"+y)
}
}
var bp=new BlackPoint()
bp.x
bp.y
bp.move(1,2)
抽象类(abstract class)
抽象类可包含未实现的方法,即抽象方法
抽象类无法实例化
抽象类使用“abstract”关键字修饰
子类重写父类抽象方法时,“override”关键字可选
子类重写父类非抽象方法,“override”关键字必写
abstract class Shape{
def draw():Unit
}
class Square extends Shape{
override def draw():Unit={
println("draw a square")
}
}
var shape=new Square
shape.draw
单例对象(object)
特质(trait)
样例类(case class)
掌握Scala单例对象的使用
Scala的类中无法定义静态成员,即无static关键字。如何像Java一样表达类的静态成员变量、成员方法与静态代码块?
Scala解决方案:单例对象
使用“object”关键字声明,可包含变量、方法与代码定义
单例对象中的成员变量、成员方法通过单例对象名直接调用
单例对象第一次被访问时初始化,并执行全部代码块
单例对象不能new,且无构造参数
程序入口main()方法必须定义在单例对象中
单例对象与同名类定义在同一文件中时形成绑定关系
定义单例对象
//Blah.scala
package test //定义包名
//定义单例对象
object Blah {
println("Blah initializing...")
def sum(l: List[Int]): Int = l.sum
}
test.Blah.sum(List[Int](1, 2, 3, 4, 5))
掌握Scala伴生对象的使用
伴生(Companion)
单例对象与同名类定义在同一文件中时形成绑定关系
同名类称为单例对象的伴生类(class)
单例对象称为同名类的伴生对象(object)
伴生类与伴生对象可相互访问各自私有成员
伴生对象可为伴生类增加静态成员
伴生类与伴生对象
//Student.scala
//伴生类
class Student(n: String, a: Int) {
private var name = n //私有变量,伴生对象可以访问
private var age = a
}
//伴生对象
object Student {
def apply(n: String, a: Int): Student = new Student(n, a)
def main(args: Array[String]): Unit = {
val stu=Student("Jason",9) //通过伴生对象的apply()方法创建实例
println(stu.name)
}
}
掌握Scala特质的使用
特质(trait)
Scala中没有接口(interface)的概念
特质用于在类之间共享程序接口和字段,类似Java接口
特质是字段和方法的集合,可以提供字段和方法实现
类和单例对象都可以扩展特质(extends)
特质不能被实例化,因此没有构造参数,类似Java接口
特质使用“trait”关键字定义
实现特质中的方法使用“override”
使用特质
import scala.collection.mutable.ArrayBuffer
trait Pet {
val name: String
def cry():Unit
}
class Dog(val name: String) extends Pet{
override def cry()=println("wow ...")
}
val dog = new Dog("Harry")
val animals = ArrayBuffer.empty[Pet]
animals.append(dog)
animals.foreach(pet => {println(pet.name);pet.cry()}) // Prints Harry wow ...
掌握Scala样例类的使用
样例类(case class)
样例类常用于描述不可变的值对象(Value Object)
case class Student(name:String,age:Int) //定义样例类
val stu=Student("Jason",19) //创建样例类的实例,无需new关键字
println(stu.name) //访问对象属性
样例类构造参数默认声明为“val”,自动实现类构造参数的getter
样例类构造参数声明为“var”时,自动实现类构造参数的setter和getter
样例类自动创建伴生对象
样例类自动实现的其他方法
toString()、equals()、copy()、hashCode()
伴生对象中的apply()、unapply()
unapply()接受一个对象,从对象中提取出相应的值,主要用于模式匹配中。
样例类与枚举
枚举(Enumeration)
object Weekday extends Enumeration {
//枚举值从0开始计数
val Mon,Tue,Wed,Thu,Fri,Sat,Sun=Value
}
//枚举的使用
Weekday.Sun
Weekday.Sun.id //获取枚举值的计数值
Weekday.values.foreach(println)
样例类与枚举区别
枚举更简单,代码更少
样例类的字段比枚举的值更强大
样例类可扩展
abstract class Term(code: String)
case class Var(name: String) extends Term(name)
case class Fun(arg: String, body: Term) extends Term(arg)
case class App(f: Term, v: Term) extends Term("App")
样例类与普通类
区别
样例类通常用于描述不可变的数据,数据完全依赖构造参数
样例类默认不可变,通过模式匹配可分解
两个样例类“==”操作时,通过按值比较而不是按引用
样例类操作更简单
最佳实践
如果一个对象在内部执行有状态计算,或者表现出其他类型的复杂行为,那么它应该是一个普通类
理解Scala泛型概念
泛型类
泛型类指可以接受类型参数的类,泛型类在集合类中被广泛使用
与Java不同,定义泛型类使用“[]”
class Stack[T] {
var elements: List[T] = Nil
def push(x: T) { elements = x :: elements }
def top: T = elements.head
def pop() {
var t = elements.head
elements = elements.tail
t
}
def showElements(){
elements.foreach(x=>print(s"$x "));println()}
}
val ms = new Stack[Int]()
ms.push(10)
ms.showElements()
ms.push(20)
ms.showElements()
val t = ms.pop()
ms.showElements()
理解包对象的使用
Scala包对象
包可以包含类、对象和特质,但不能包含变量或方法的定义,应使用包对象解决这个问题
package com.kgc{
package object scala { //对应包com.kgc.scala,每个包都可以有一个包对象
val name="Wow"
}...
package scala{...}//与包对象同名的包可直接使用包对象中定义的变量和方法
}