购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.6 抽象类和特质

1.6.1 抽象类

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修饰。

1.6.2 特质

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,代码如下: DEN9zoTYTzH8pCcO91o9AZMs4rWUbxWKS7nvYbFuglprtJOgXbqVPjHhmMNUwz11

    val bird=new Bird() with Runable with Flyable
    bird.run //输出结果“会跑”
    bird.fly //输出结果“会飞”
点击中间区域
呼出菜单
上一章
目录
下一章
×