I. 类
- 类的定义
- 类成员的可见性
- 方法的定义方式
- 构造器
1. 类的定义
class Classname{var v = 0val vl = 1def func(args): return_type = {content} // 无返回Unit}class Counter{var value = 0def increment(step: Int): Unit = {value += step}def current(): Int = {value}}// 实例化val myCounter = new CountermyCounter.value = 5myCounter.increment(3)println(myCounter.current) // 调用无参数方法时,可以省略方法后的括号
2. 类的可见性
当没有修饰词时,成员默认为public
私有成员:
- private -> 本类型和嵌套类型可见
- protected -> 本类型和其他继承类型可见
建议编程中不要直接定义(暴露)public字段,而是通过getter/setter函数去操作某些私有变量。
下面两个方法成对出现:
- value = 类似getter方法
- value_= 一个方法名称,类似setter方法
class Counter{private var privateValue = 0def value = privateValuedef value_ = (newValue: Int){if(newValue > 0) privateValue = newValue}...}val myCounter = new CountermyCounter.value_=(3) // 可简化为 myCounter.value = 3println(myCounter.value) // out: 3 其中.value是一个方法
3. 方法的定义方式
def func(args:arg_type): return_type = {...}
- 参数不可使用val/var修饰的
- 没有参数时,可以省略括号;同时后面定义时必须省略
- 可以使用中缀操作符调用方法
a.+(b) -> a+b - 方法体中只有一条语句时,可省略大括号
- 当无返回值时,可以省略:
Unit=class Counter{var value = 0// def increment(step:Int):Unit = {value += step}def increment(step:Int){value += step}def current() = value // value的类型可以自动推断出来,所以不需要声明}
4. 构造器
类名称(参数列表)
- 类本身作为主构造器 this
- 可以加val/var修饰。同时自动成为类内成员,自动创造读写方法
- 如果没有val/var修饰,作用又是为了传递参数
class Counter(var name: String)var mycounter = new Counter("Runner")mycounter.name_=("Timer")println(mycounter.name) // out: Timer
辅助构造器
一个类:主构造器 + 多个辅助构造器 this 表示当前类对象
- 每个辅助构造器必须调用前一个构造器
```scala
class Counter{
private var value = 0
private var name = “”
private var step = 1
println(“the main constructor”)
def this(name: String){
this.name = name printf(f”the 2nd constructor: $name\n”) } def this(name: String, step: Int){this() // 调用主构造器
this.step = step printf(f”the 3rd constructor: $name\n”) } def increment(step: Int): Unit = {value += step} def current(): Int = {value} }this(name) // 调用前一个辅助构造器
val c1 = new Counter // 主构造器 val c2 = new Counter(“the second Counter”) // 第二个构造器 val c3 = new Counter(“the third Counter”, 3)
---<a name="JPkhF"></a># II. 对象- 单例对象- update方法- apply方法- unapply方法<a name="5PSbr"></a>## 1. 单例对象- 静态的方法调用,会记住之前的状态,不会重置- 不需要实例化,可以直接调用静态方法```scalaobject Person{private var lastId = 0def newPersonId() = {lastId += 1lastId // 方法返回值}}printf(f"The first person id: $Person.newPersonId()")
单例对象分两类
- 伴生对象
- 一个文件中同时出现
class A{}; object A{} - 互为伴生对象,可以互相访问类内部的变量和方法
- 一个文件中同时出现
- 孤立对象
2. apply**
为什么声明一个数组对象时,不需要new?
- 因为scala会自动帮你调用Array这个类的伴生对象中apply方法,创建一个数组对象
val myStrArr = Array("BigData", "Hadoop", "Spark")
apply调用约定
- 作为一种工厂方法,用于生成类
- 括号传递给类实例/单例对象名称参数时自动调用apply
- scala会在相应的类中查找方法名为apply
- apply参数列表需要与传入的参数一致
- 调用apply方法
class TestApplyClass{def apply(param: String){println("apply method called: " + param)}}
我们可以将类的构造方法以apply方法的形式,写入伴生对象中。在实例化时,自动调用apply方法,自动生成类。
class Car(name: String){def info(){println("Car name is " + name)}}object Car{def apply(name: String) = new Car(name)}// 孤立对象: 定义程序的入口函数object MyTestApply{def main(args: Array[String]){val mycar = Car("BMW") // 调用伴生对象中的apply方法mycar.info() // out: Car name is BMW}}
JAVA使用类过程
- 定义一个类
- new class
- new 一个类,生成一个实例
Scala为了融合面向对象和函数式编程
- 面向对象:对象.方法
- 函数式:函数名称(参数)
def add = (x: Int, y: Int) => x+y //匿名函数add(4, 5) // 函数调用add.apply(4, 5) // 对象调用
3. update
- 当对带有括号并包括一到若干参数的对象进行赋值时
- 编译器将调用update方法
- 并将括号里的参数和等号右边的值
- 一起作为update方法的输入参数来执行调用
val myStrArr = new Array[String](3)myStrArr(0) = "BigData" //调用伴生类Array中update方法执行myStrArr.update(0, "BigData")
4. unapply
给定对象后,提取对象中的变量,解构过程
object Car{def unapply(c: Car): Option[(String, Int)] = {Some((c.brand, c.price))}}object TestUnapply{def main(args: Array[String]){// 等号右侧apply构造,左侧unapply解构var Car(carbrand, carprice) = Car("BMW", 800000)println("brand: " + carbrand + "and carprice" + carprice)}}
III. 继承
- 抽象类
- option类
- 扩展类
- Scala的类层次结构
1. 抽象类
一个类中包含没有被实现的成员变量/成员函数,称为抽象类,必须用 abstract 修饰
- 抽象字段必须给定变量类型
abstract class Car(val name: String){val carBrand: String // 字段没有初始值,是抽象字段def info() // 抽象方法def greeting(){println("Welcome to my car!")}}
2. 扩展类 (子类)
extends 关键字表示继承关系;override 覆盖成员
- 父类中已实现的方法,子类覆盖时必须添加
override - 父类中的抽象方法,子类实现时可不加
override - 只能重载val字段,不可重载var类型字段 ```scala class BMWCar extends Car{ override val carBrand = “BMW” def info(){ println(“Expensive!”) } override def greeting(){println(“BWM car!”)} }
Object MyCar{ def main(args: Array[string]) val myCar1 = new BMWCar() myCar1.greeting() myCar1.info() }
<a name="ijevc"></a>## 3. 层次结构- AnyVal 是值类型,存入寄存器,之后进行运算- AnyRef 引用类型,new实例化对象后存入堆中,指针指向堆地址 null为子类<a name="Plul8"></a>## 4. option类**实际编程中尽量避免使用Null,改用Option类**- Option类将返回值封装为Some对象,返回- 如果没有返回值,返回Null- 当无法确定返回值,最好将返回值类型设定为Option```scalacase class Book(val name: String, val price: Double)val books = Map("hadoop" -> Book("Hadoop", 35.5)"spark" -> Book("Spark", 55.5))$ books.get("hadoop")res0: Option[Book] = Some(Book(Haddop, 35.5))$ books.get("Hive")res1: Option[Book] = None$ books.get("hadoop").getres2: Book = Book(Hadoop, 35.5)$ boos.get("hive").getOrElse(Book("Unknown name", 0))Book = Book(Unknown name, 0.0)
IV. 特质 trait
Scala 中特有的概念,类似Java中的接口
- 定义抽象方法/方法的具体方法
trait - 可继承,混入多个特质 -> 实现多重继承
with/extends```scala trait Flyable{ var maxFlyHeight: Int //抽象字段 def fly()
def breathe(){
} }println("I can breathe.")
class Bird(flyHeight: Int) extends Flyable{ var maxFlyHeight: Int = flyHeight def fly(){ printf(“fly %d”, maxFlyHeight) } }
val b = new Bird(100) b.fly() // fly 100 b.breathe // I can breathe
trait HasLegs{…} class Animal(val category: String){…}
class Bird(flyHeight: Int) extends Animal(“Bird”) with Flyable with HasLegs{ var maxFlyHeight: Int = flyHeight val legs = 2 def fly(){println(‘fly: ‘ + maxFlyHeight)} }
---<a name="Ic6A7"></a># V. 模式匹配<a name="Nvs26"></a>## 1. **match-case**- 可以添加守卫 guard```scalaimport scala.io.StdIn._println("Please input the score: ")val grade = readChar()grade match{case "A" => println("85-100")case "B" => println("70-84")case_ => println("error input!")}for(elem <- List(1, 2.2, "Spark")){val str = elem match{case i: Int => "int"case d: Double => "double"case s: String => "string"case_ => "unexpected value"}println(str)}// guard 在每次操作时加入条件判断for(elem <- List(1,2,3,4)){elem match{case_ if(elem%2==0) => println(elem+"is even.")case_ => println(elem + "is odd.")}}
2. case类
- 自动重载许多实用方法
toString/equals/hashcode - 自动生成一个伴生对象 apply工厂方法自动生成实例,不需要new;还有unapply方法 ```scala case class Car(brand: String, price: Int)
// 上一句case类自动生成下面伴生对象 object Car{ def apply(brand: String, price: Int) = new Car(brand, price) def unapply(c: Car): Option[(String, Int)] = Some((c.brand, c.price)) }
// 用于模式匹配 case class Car(brand: String, price: Int) val myBYD = Car(“BYD”, 89000) val myBMW = Car(“BMW”, 1200000) for(car <- List(myBYD, myBMW)){ car match{ case Car(“BYD”, 89000) => println(“BYD”) //apply case Car(brand, price) => println(“Brand: “ + brand) //unapply } }
---<a name="yrrT5"></a># VI. 包解决程序中的命名冲突- 通配符:下划线`_`- scala隐式添加 `java.lang._` `scala._` `Predef._````scala# 嵌套定义package xmu{package autodepartment{class ControlCourse{...}}package csdepartment{class OSCourse{val cc = new autodepartment.ControlCourse}}}# 导入使用import xmu.autodepartment.ControlCourseclass MyClass{var myos = new ControlCourse}
