



Scala的抽象类使用关键字abstract定义,具有以下特征:
· 抽象类不能被实例化。
· 抽象类中可以定义抽象字段(没有初始化的字段)和抽象方法(没有被实现的方法),也可以定义被初始化的字段和被实现的方法。
· 若某个子类继承了一个抽象类,则必须实现抽象类中的抽象字段和抽象方法,且实现的过程中可以添加override关键字,也可以省略。若重写了抽象类中已经实现的方法,则必须添加override关键字。
例如,定义一个抽象类Person,代码如下:
//定义抽象类Person
abstract class Person {
//抽象字段
var name:String
var age:Int
//普通字段
var address:String="北京"
//抽象方法
def speak()
//普通方法
def eat():Unit={
println("吃东西")
}
}
定义一个普通类Teacher,并继承抽象类Person,实现Person中的抽象字段和抽象方法,并重写方法eat(),代码如下:
//继承了抽象类Person
class Teacher extends Person{
//实现抽象字段
var name: String = "王丽"
var age: Int = 28
//实现抽象方法
def speak(): Unit = {
println("姓名:"+this.name)
println("年龄:"+this.age)
println("地址:"+this.address)//继承而来
println("擅长讲课")
}
//重写非抽象方法,必须添加override关键字
override def eat():Unit={
println("爱吃中餐")
}
}
定义一个测试对象,调用Teacher类中的方法,代码如下:
object AppTest{
def main(args: Array[String]): Unit = {
val teacher=new Teacher()
//调用方法
teacher.speak()
teacher.eat()
}
}
输出结果如下:
姓名:王丽
年龄:28
地址:北京
擅长讲课
爱吃中餐
需要注意的是,上述Teacher类中speak()方法的地址字段(address)是从父类(抽象类Person)中继承而来的。由于该字段在Person中有初始化值,不是抽象字段,若需要在Teacher类中修改该字段的值,则可以在Teacher类的构造函数或其他方法中使用this.address对其重新赋值。例如,将地址改为“上海”,可以使用以下代码:
this.address="上海"
由于Person类中的address字段使用var修饰,而Scala不允许对抽象类中var修饰的非抽象字段进行重写,因此在Teacher类中对address字段进行重写将报编译错误,除非该字段在Person类中的声明是不可变的,即使用val修饰。
Scala特质使用关键字trait定义,类似Java 8中使用interface定义的接口。特质除了有Java接口的功能外,还有一些特殊的功能。下面分别进行讲解。
Scala特质中,字段和方法的定义与Scala抽象类一样,可以定义抽象字段和抽象方法、非抽象字段和非抽象方法。例如以下代码定义了一个特质Pet:
//定义特质(宠物)
trait Pet {
//抽象字段
var name:String
var age:Int
//抽象方法
def run
//非抽象方法
def eat: Unit ={
println("吃东西")
}
}
类可以使用关键字extends实现特质,但必须实现特质中未实现的字段和方法(抽象字段和抽象方法),这一点与继承抽象类是一致的。例如以下代码定义了一个普通类Cat,实现了上述特质Pet:
//定义类(猫)继承特质(宠物)
class Cat extends Pet{
//实现抽象字段
var name:String="john"
var age:Int=3
//实现抽象方法
def run: Unit = {
println("会跑")
}
//重写非抽象方法
override def eat: Unit ={
println("吃鱼")
}
}
如果需要实现的特质不止一个,那么可以通过with关键字添加额外特质,但位于最左侧的特质必须使用extends关键字。例如,类Dog同时实现了特质Pet、Animal和Runable,代码如下:
trait Animal{
}
trait Runable{
}
//类Dog实现了3个特质
class Dog extends Pet with Animal with Runable{
//省略
}
在类实例化的时候,也可以通过with关键字混入多个特质,从而使用特质中的方法。例如以下代码定义了两个特质Runable、Flyable和一个类Bird:
//定义两个特质
trait Runable{
def run=println("会跑")
}
trait Flyable{
def fly=println("会飞")
}
//定义一个类
class Bird{
}
在类Bird实例化时混入特质Runable和Flyable,代码如下:
val bird=new Bird() with Runable with Flyable
bird.run //输出结果“会跑”
bird.fly //输出结果“会飞”