1.6 抽象类和特质
1.6.1 抽象类
Scala的抽象类使用关键字abstract定义,具有以下特征:
• 抽象类不能被实例化。
• 抽象类中可以定义抽象字段(没有初始化的字段)和抽象方法(没有被实现的方法),也可以定义被初始化的字段和被实现的方法。
• 若某个子类继承了一个抽象类,则必须实现抽象类中的抽象字段和抽象方法,且实现的过程中可以添加override关键字,也可以省略。若重写了抽象类中已经实现的方法,则必须添加override关键字。
例如,定义一个抽象类Person,代码如下:
定义一个普通类Teacher,并继承抽象类Person,实现Person中的抽象字段和抽象方法,并重写方法eat(),代码如下:
定义一个测试对象,调用Teacher类中的方法,代码如下:
输出结果如下:
姓名:王丽 年龄:28 地址:北京 擅长讲课 爱吃中餐
需要注意的是,上述Teacher类中speak()方法的地址字段(address)是从父类(抽象类Person)中继承而来的。由于该字段在Person中有初始化值,不是抽象字段,若需要在Teacher类中修改该字段的值,则可以在Teacher类的构造函数或其他方法中使用this.address对其重新赋值。例如,将地址改为“上海”,可以使用以下代码:
this.address="上海"
由于Person类中的address字段使用var修饰,而Scala不允许对抽象类中var修饰的非抽象字段进行重写,因此在Teacher类中对address字段进行重写将报编译错误,除非该字段在Person类中的声明是不可变的,即使用val修饰。
1.6.2 特质
Scala特质使用关键字trait定义,类似Java 8中使用interface定义的接口。特质除了有Java接口的功能外,还有一些特殊的功能。下面分别进行讲解。
Scala特质中,字段和方法的定义与Scala抽象类一样,可以定义抽象字段和抽象方法、非抽象字段和非抽象方法。例如以下代码定义了一个特质Pet:
类可以使用关键字extends实现特质,但必须实现特质中未实现的字段和方法(抽象字段和抽象方法),这一点与继承抽象类是一致的。例如以下代码定义了一个普通类Cat,实现了上述特质Pet:
如果需要实现的特质不止一个,那么可以通过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 //输出结果“会飞”