Scala中的抽象类

61 阅读5分钟

1. 抽象类的定义和实现;

2. 抽象类的继承;

3. 抽象类的重写。

(一)理解抽象类

类本身就是对对象的抽象,抽象类就是对类的抽象,就是一种更加模糊的类。

定义:抽象类是一个包含一个或多个抽象方法的类。抽象方法是不带任何实现的方法。抽象类也可以包含具体的方法和属性。

目的:抽象类的主要目的是为子类提供公共的接口和部分实现,并确保子类实现抽象方法。

(二)定义抽象类

/* 抽象类 abstract
* 1. 一个抽象类(加了abstract修饰的),不能被new。
* 一个类不能直接用来创建对象,那么这个类具体有什么用呢? 做别人的父类!
*/
object Main {
    abstract class AICar {
        def autoDrive(): Unit = {
            println("具体方法,自动驾驶......")
        }
    }
    
    class SU7 extends AICar {
    }

    def main(args: Array[String]): Unit = {
        // val can1 = new AICan {}  // 错误:抽象类不能被实例化
        val su = new SU7()
        su.autoDrive()
    }
}

抽象类的关键特性:

  1. 不能被实例化new AICar() 会编译错误
  2. 可以包含抽象成员:抽象方法、抽象字段
  3. 可以包含具体成员:具体方法、具体字段
  4. 作为父类:为子类提供通用接口和部分实现
  5. 强制实现:子类必须实现所有抽象成员

抽象类的主要用途:

  • 定义通用接口:为相关类提供统一的接口
  • 代码复用:通过具体方法提供通用实现
  • 强制规范:要求子类实现特定的功能
  • 模板方法模式:定义算法骨架,子类实现具体步骤

(三)继承抽象类

子类继承了抽象类,它就必须去实现所有抽象属性和抽象方法

1. 基本语法和规则

abstract class Animal {
    // 抽象字段
    val species: String
    
    // 抽象方法
    def makeSound(): Unit
    
    // 具体方法
    def eat(): Unit = {
        println(s"$species 在吃东西")
    }
    
    // 具体字段
    val hasTail: Boolean = true
}

// 继承抽象类必须实现所有抽象成员
class Dog extends Animal {
    override val species: String = "狗"
    
    override def makeSound(): Unit = {
        println("汪汪汪")
    }
}

class Cat extends Animal {
    override val species: String = "猫"
    
    override def makeSound(): Unit = {
        println("喵喵喵")
    }
    
    // 可以选择性重写具体方法
    override def eat(): Unit = {
        println(s"$species 小口小口地吃东西")
    }
}

2. 必须实现所有抽象成员

abstract class Shape {
    // 抽象字段
    val name: String
    val color: String
    
    // 抽象方法
    def area(): Double
    def perimeter(): Double
    
    // 具体方法
    def display(): Unit = {
        println(s"形状: $name, 颜色: $color")
    }
}

// 正确实现:实现了所有抽象成员
class Circle(val radius: Double) extends Shape {
    override val name: String = "圆形"
    override val color: String = "红色"
    
    override def area(): Double = math.Pi * radius * radius
    override def perimeter(): Double = 2 * math.Pi * radius
}

// 错误示例:如果没有实现所有抽象成员会编译错误
/*
class IncompleteShape extends Shape {
    // 缺少 area() 和 perimeter() 的实现
    override val name: String = "未完成形状"
    override val color: String = "黑色"
}
*/

3. 构造器参数传递

abstract class Vehicle(val brand: String, val year: Int) {
    def start(): Unit
    def stop(): Unit
    def getInfo(): String
}

class Car(brand: String, year: Int, val model: String) extends Vehicle(brand, year) {
    override def start(): Unit = {
        println(s"$brand $model 启动")
    }
    
    override def stop(): Unit = {
        println(s"$brand $model 停止")
    }
    
    override def getInfo(): String = {
        s"车辆: $brand $model, 年份: $year"
    }
}

class Bicycle(brand: String, year: Int, val gearCount: Int) extends Vehicle(brand, year) {
    override def start(): Unit = {
        println(s"$brand 自行车开始骑行")
    }
    
    override def stop(): Unit = {
        println(s"$brand 自行车停下")
    }
    
    override def getInfo(): String = {
        s"自行车: $brand, 年份: $year, 档位: $gearCount"
    }
}

4. 多层继承

// 第一层:抽象类
abstract class Employee(val name: String) {
    def work(): Unit
    def getSalary(): Double
}

// 第二层:抽象类
abstract class Developer(name: String, val programmingLanguage: String) 
    extends Employee(name) {
    
    def code(): Unit
    override def work(): Unit = {
        println(s"$name 正在工作")
        code()
    }
}

// 第三层:具体类
class JavaDeveloper(name: String) extends Developer(name, "Java") {
    override def code(): Unit = {
        println(s"$name 正在用 Java 编写代码")
    }
    
    override def getSalary(): Double = 15000.0
}

class ScalaDeveloper(name: String) extends Developer(name, "Scala") {
    override def code(): Unit = {
        println(s"$name 正在用 Scala 编写函数式代码")
    }
    
    override def getSalary(): Double = 18000.0
    
    // 可以添加子类特有的方法
    def functionalProgramming(): Unit = {
        println("进行函数式编程")
    }
}

5. 使用 super 调用父类方法

abstract class Notification {
    def send(message: String): Unit = {
        println("发送通知...")
    }
    
    def getType(): String
}

class EmailNotification extends Notification {
    override def getType(): String = "邮件通知"
    
    override def send(message: String): Unit = {
        // 先调用父类的实现
        super.send(message)
        // 然后添加子类特有的逻辑
        println(s"通过邮件发送: $message")
        println("邮件发送完成")
    }
}

class SMSNotification extends Notification {
    override def getType(): String = "短信通知"
    
    override def send(message: String): Unit = {
        super.send(message)
        println(s"通过短信发送: $message")
        println("短信发送完成")
    }
}

6. 完整的测试示例

object AbstractClassInheritance {
    
    abstract class Product(val name: String, val price: Double) {
        def getDescription(): String
        def calculateDiscount(): Double
        final def getFinalPrice(): Double = price - calculateDiscount()
    }
    
    class Book(name: String, price: Double, val author: String, val pages: Int) 
        extends Product(name, price) {
        
        override def getDescription(): String = {
            s"书籍: $name, 作者: $author, 页数: $pages, 价格: ¥$price"
        }
        
        override def calculateDiscount(): Double = {
            if (price > 50) price * 0.1 else 0.0
        }
    }
    
    class Electronics(name: String, price: Double, val warranty: Int) 
        extends Product(name, price) {
        
        override def getDescription(): String = {
            s"电子产品: $name, 价格: ¥$price, 保修: $warranty 年"
        }
        
        override def calculateDiscount(): Double = {
            price * 0.15  // 电子产品统一85折
        }
    }

    def main(args: Array[String]): Unit = {
        // 测试之前的例子
        val dog = new Dog
        val cat = new Cat
        
        println("=== 动物测试 ===")
        dog.makeSound()
        dog.eat()
        cat.makeSound()
        cat.eat()
        
        println("\n=== 形状测试 ===")
        val circle = new Circle(5.0)
        circle.display()
        println(s"面积: ${circle.area()}")
        println(s"周长: ${circle.perimeter()}")
        
        println("\n=== 车辆测试 ===")
        val car = new Car("丰田", 2023, "凯美瑞")
        val bicycle = new Bicycle("捷安特", 2022, 21)
        println(car.getInfo())
        println(bicycle.getInfo())
        
        println("\n=== 开发者测试 ===")
        val javaDev = new JavaDeveloper("张三")
        val scalaDev = new ScalaDeveloper("李四")
        javaDev.work()
        println(s"薪资: ${javaDev.getSalary()}")
        scalaDev.work()
        println(s"薪资: ${scalaDev.getSalary()}")
        
        println("\n=== 产品测试 ===")
        val book = new Book("Scala编程", 65.0, "Martin Odersky", 300)
        val laptop = new Electronics("笔记本电脑", 5000.0, 2)
        
        println(book.getDescription())
        println(s"最终价格: ¥${book.getFinalPrice()}")
        
        println(laptop.getDescription())
        println(s"最终价格: ¥${laptop.getFinalPrice()}")
    }
}

继承抽象类的关键点:

  1. 必须实现所有抽象方法和字段
  2. 可以重写具体方法和字段
  3. 可以使用 super 调用父类实现
  4. 可以添加子类特有的成员
  5. 支持多层继承关系
  6. 构造器参数可以传递给父类
object Main {
    /*
    * 抽象类 abstract
    * 1. 一个抽象类(加了abstract修饰的),不能被new。
    * 一个类不能直接用来创建对象,那么这个类具体有什么用呢? 做别人的父类!
    * 2. 可以定义抽象方法,在子类中去实现
    */
    
    abstract class AICar {
        // 抽象方法:没有具体的函数代码。
        def autoEn(): Unit
        
        // 具体方法
        def autoDrive(): Unit = {
            println("具体方法:自动驾驶......")
        }
    }

    // 在子类中,一定要去实现父类的所有抽象方法
    class SU7 extends AICar {
        // 使用override 去实现这个方法
        override def autoEn(): Unit = {
            println(s"采用小米独家的无线充电技术,停车就可以充电")
        }
    }

    def main(args: Array[String]): Unit = {
        // val can1 = new AICan ()  // 错误:抽象类不能被实例化
        val su = new SU7()
        su.autoEn()
        su.autoDrive()
    }
}

抽象类为面向对象设计提供了强大的基础,特别是在需要定义通用接口但又需要部分实现的场景中。

(四)抽象类重写

如果子类中对抽象类中的方法定义不满意,仍可以使用override去覆盖的。

image.png

object Main {
    /*
    * 2. 可以定义抽象方法,在子类中去实现
    * 
    * 3. 一个抽象类中可以有:
    * 1. 具体属性    val name:String = "小米"
    * 2. 具体方法    def autoRun():Unit = {}
    * 3. 抽象属性:val name:String 没有具体值的属性。只有属性名和类型。它必须写在抽象类中
    * 4. 抽象方法:def autoRun():Unit
    *     在子类中,要有具体的实现。
    */
    
    abstract class AICar() {
        // 抽象属性
        val name: String
        
        // 抽象方法
        def autoRun(): Unit
    }

    class Xiaomi extends AICar {
        // 实现抽象属性
        override val name: String = "xiaomi"
        
        // 实现抽象方法
        override def autoRun(): Unit = {
            println("小米汽车,自动驾驶......")
        }
    }

    def main(args: Array[String]): Unit = {
        val car1 = new Xiaomi()
        car1.autoRun()
        println(s"汽车品牌: ${car1.name}")
    }
}

抽象类中可以包含的成员:

  1. 抽象属性val name: String(子类必须实现)
  2. 抽象方法def method(): Unit(子类必须实现)
  3. 具体属性val count: Int = 0(子类可以继承或重写)
  4. 具体方法def commonMethod(): Unit = {...}(子类可以继承或重写)
/*
3. 一个抽象类中可以有:
1. 具体属性 val name:String = "小米"
2. 具体方法 def autoRun():Unit = {}

3. 抽象属性:val name:String 没有具体值的属性,只有属性名和类型
4. 抽象方法:def autoRun():Unit
在子类中,要有具体的实现。
*/

object Main {

  abstract class AICar() {
    // 1. 具体属性
    var name: String = "car"
    val color: String = "black"

    // 2. 具体方法
    def run(): Unit = {
      println("AICar run......")
    }

    // 3. 抽象属性,没有属性值
    var price: Double

    // 4. 抽象方法,没有方法体
    def autoRun(): Unit
  }

  class XiaoMI extends AICar {
    // 重写
    // 1. 具体属性
    name = "小米"  // 对于var的属性,直接覆盖
    override val color: String = "流水紫"  // 对于val的属性,要添加override

    // 2. 具体方法
    override def run(): Unit = {
      println("小米 run......")
    }

    // 实现
    // 3. 实现 抽象属性
    var price: Double = 28.8

    // 4. 实现 抽象方法
    def autoRun(): Unit = {
      println("小米自动驾驶")
    }
  }

  def main(args: Array[String]): Unit = {
    val cl = new XiaoMI()
    cl.autoRun()
    cl.run()
    println(cl.name)
    println(cl.color)
    println(s"价格: ${cl.price}万")
  }
}

总结:

  1. var 属性:直接重新赋值
  2. val 属性:使用 override 重写
  3. 抽象属性:必须在子类中实现
  4. 具体方法:可以选择性重写
  5. 抽象方法:必须在子类中实现