面向对象编程基础
1. 类
1.1 类的定义
创建类
class Counter {
private var value = 0
//Unit表示返回空值
//若果大括号里面只有一行语句,那么也可以直接去掉大括号。
def increment(): Unit = { value += 1}
def current(): Int = {value}
//可以去掉返回值类型和等号,只保留大括号
def increment() {value += 1}
创建对象
val myCounter = new Counter
myCounter.increment() //若没有参数,可以省略圆括号
println(myCounter.current)
1.2 编译和执行
在未定义object的情况下:
声明没有被封装在对象中,因此,无法编译成JVM字节码
scala TestCounter.scala
进入到scala解释器下执行TestCounter.scala
:load TestCounter.scala
在定义object的情况下:
scalac TestCounterJVM.scala
scala [-classpath] MyCounter //MyCounter是object的名称。
1.3 getter和setter方法
- 将private var value 改为 var value,即将变量变为公有变量
println(mycounter.value) //getter
mycounter.value = 3 //setter
- value和value_方法
class Counter {
private var privateValue = 0 //变成私有字段,并且修改字段名称
def value = privateValue //定义一个方法,方法的名称就是原来我们想要的字段的名称
def value_=(newValue: Int){
if ( newValue > 0) privateValue = newValue //只有提供的新值是正数,才允许修改
}
1.4 构造器
Scala构造器包含1个主构造器和若干个辅助构造器。
辅助构造器的名称为this,每个辅助构造器都必须调用一个此前已经定义的辅助构造器或主构造器。
class Counter {
private var value = 0
private var name = ""
private var mode = 1
def this(name: String){
this() //调用主构造器
this.name = name
}
def this(name: String, mode: Int){
this(name) //调用前一个辅助构造器
this.mode = mode
}
def increment(step: Int): Unit = { value += step}
def current(): Int = {value}
def info(): Unit = {printf("Name:%s and mode is %d\n", name, mode)}
}
object MyCounter{
def main(args:Array[String]){
//根据传入参数个数选择构造器
val myCounter1 = new Counter //主构造器
val myCounter2 = new Counter("Runner") //第一个辅助构造器,计数器的名称设为Runner,用来计算跑步步数
val myCounter3 = new Counter("Timer", 2) //第二个辅助构造器,计数器的名称设为Timer,用来计算秒数
myCounter1.info //显示计数信息
myCounter1.increment(1) //设置步长
printf("Current Value is: %d\n", myCounter1.current) //显示计数器当前值
myCounter2.info //显示计数信息
myCounter2.increment(2) //设置步长
printf("Current Value is: %d\n", myCounter2.current) //显示计数器当前值
myCounter3.info //显示计数信息
myCounter3.increment(3) //设置步长
printf("Current Value is: %d\n", myCounter3.current) //显示计数器当前值
}
}
Scala的每个类都有主构造器,Scala的主构造器就是整个类。
class Counter(val name: String, val mode: Int)
//括号内的即为主构造器,编译时即自动编译为字段。
对象
单例对象和伴生对象
单例对象:
采用object关键字实现单例对象。无需定义类,即可定义对象。
单例对象中的字段,类似于JAVA中的静态方法。每次调用的值是在前一次调用的基础上进行计算。
伴生对象:
类似于Java中,同时包含实例方法和静态方法的类。
- 当单例对象与某个类具有相同的名称时,它被称为这个类的“伴生对象”
- 类和它的伴生对象必须存在于同一个文件中而且可以相互访问私有成员(方法或字段)
应用程序对象:
每个Scala应用程序都必须从一个对象的main方法开始。若没有class类,则可直接运行scala ,
否则需使用scalac编译。
apply方法和update方法
系统会自动调用apply方法和update方法。
用括号传递给给变量(对象)一个或多个参数时,Scala会把它转换成对apply方法的调用。
class TestApplyClass {
def apply(param: String): String = {
println("apply method called, parameter is: " + param)
"Hello world" //该字符串作为返回值。
}
}
val myObject = new TestApplyClass
println(myObject("param1")
系统自动调用Aaary的伴生对象的apply方法。
val myStrArr = Array("BigData", "Hadoop", "Spark")
update方法:
val myStrArr = new Array[String](3)
myStrArr(0) = "Bigdata" //实际上,调用了伴生类Array中的update方法,执行myStrArr.update(0, "Bigdate")
myStrArr(1) = "Hadoop" //实际上,调用了伴生类Array中的update方法,执行myStrArr.update(1, "Hadoop")
myStrArr(2) = "Spark" //实际上,调用了伴生类Array中的update方法,执行myStrArr.update(2, "Spark")
当对带有括号并包括一到若干参数的对象进行赋值时,编译器将调用对象的update方法,在调用时,是把括号里的参数和等号右边的对象一起作为update方法的输入参数来执行调用。
继承
Scala中的继承与Java有着显著的不同
- 重写一个非抽象方法必须使用override修饰符
- 可以重写超类中的字段
- 只有主构造器可以使用超类的主构造器
- 在子类中重写超类的抽象方法是不需要使用override关键字
Scala和Java一样,不允许从多个类中继承。
抽象类:
abstract class Car{ //是抽象类,不能直接被实例化
val carBrand: String //字段没有初始化值,就是一个抽象字段
def info() //抽象方法,不需要使用abstract关键字
def greeting() {println("Welcome to my cal")
}
定义抽象类的注意点:
- 定义一个抽象类,需要使用关键字abstract
- 定义一个抽象类的抽象方法,也不需要关键字abstract,只要把方法体空着不写方法体就可以
- 抽象类中定义的字段,只要没有给出初始值,就表示是一个抽象字段,但是,抽象字段必须要声明类型。
扩展类:
class BWMCar extends Car {
override val carBrand = "BEM" //重写超类字段,需要使用override关键字
def info {printf("This is a %s car , It is on sale", carBrand)} //创协超类的抽象方法时,不需要使用override关键字
override def greeting() {println("Welcome to my BWM car")} //重写超类的非抽象方法,必须使用override关键字。
特质
实现了Java中接口的功能:重用特质中的方法和字段,实现了多重继承。还有其他许多特征
trait CarId{
var id: Int
def currentId(): Int //特质中没有方法体的方法,默认就是抽象方法
}
把特质混入类中
class BWMCar extends CarId {
override var id = 2000
def currentId(): Int = { id += 1; id}
}
特质中可以包含具体方法或字段。
使用extends混入第一个特质,后面可以反复使用with关键字混入更多特质。实例化对象后,可以直接使用特质内的方法字段。
class BWMCaId extends CarId with CarGreeting
模式匹配
简单匹配:
Scala的模式匹配最常用语match语句中:
val colorNum = 1
val colorStr = colorNum match {
case 1 => "red"
case 2 => "green"
case _ => "Not Allowed"
}
另外,在模式匹配中的case语句中,还可以使用变量
val colorNum = 1
val colorStr = colorNum match {
case 1 => "red"
case 2 => "green"
case unexpected => unexpected + "is Not Allowed"
}
类型模式:
for (elem <- List(9,12.3,"Spark", "Hadoop", "Hello")){
val str = elem match{
case i: Int => i + " is an int value"
case d: Double => d + " is an double value"
case "Spark" => "Spark is found"
case s: String => s + " is an string value"
case _ => "This is an unexpected value"
}
println(str)
}
守卫语句:
在模式匹配中添加一些必要的处理逻辑