Abstract Class

255 阅读2分钟

在面向对象编程中,抽象类(Abstract Class)是一种不能被实例化的类,主要用于定义抽象行为(未实现的方法)和共性属性,供子类继承并实现具体逻辑。以下结合 Scala 语言,详细说明抽象类的定义、继承与重写。

1. 抽象类的定义和实现

抽象类通过abstract class关键字定义,可包含:

  • 抽象方法:只声明方法签名,无具体实现(子类必须重写)。
  • 具体方法:有完整实现的方法(子类可直接复用或重写)。
  • 属性:可包含具体属性或抽象属性(无初始值,子类必须实现)。

**示例:定义一个抽象类Shape**假设我们需要设计几何图形类,所有图形都有 “计算面积” 和 “计算周长” 的行为,但具体实现因图形而异。

scala

kotlin

// 定义抽象类Shape
abstract class Shape {
  // 抽象属性:图形名称(无初始值,子类必须实现)
  val name: String

  // 抽象方法:计算面积(无实现,子类必须重写)
  def area(): Double

  // 抽象方法:计算周长(无实现,子类必须重写)
  def perimeter(): Double

  // 具体方法:打印图形信息(有实现,子类可直接使用)
  def printInfo(): Unit = {
    println(s"图形:$name,面积:${area()},周长:${perimeter()}")
  }
}

说明

  • Shape是抽象类,无法直接实例化(如new Shape()会编译报错)。
  • name是抽象属性,子类必须定义具体值。
  • area()perimeter()是抽象方法,子类必须实现具体逻辑。
  • printInfo()是具体方法,子类可直接复用。

2. 抽象类的继承

子类通过extends关键字继承抽象类,必须实现抽象类中所有未实现的抽象属性和方法(否则子类也需声明为抽象类)。

示例:继承Shape实现具体图形类实现Circle(圆形)和Rectangle(矩形)类,继承Shape并实现抽象成员。

scala

scala
 体验AI代码助手
 代码解读
复制代码
// 1. 圆形类:继承Shape
class Circle(val radius: Double) extends Shape {
  // 实现抽象属性name
  override val name: String = "圆形"

  // 实现抽象方法:面积 = π * r²
  override def area(): Double = math.Pi * radius * radius

  // 实现抽象方法:周长 = 2πr
  override def perimeter(): Double = 2 * math.Pi * radius
}

// 2. 矩形类:继承Shape
class Rectangle(val length: Double, val width: Double) extends Shape {
  // 实现抽象属性name
  override val name: String = "矩形"

  // 实现抽象方法:面积 = 长 * 宽
  override def area(): Double = length * width

  // 实现抽象方法:周长 = 2*(长+宽)
  override def perimeter(): Double = 2 * (length + width)
}

说明

  • 子类CircleRectangle必须用override关键字实现Shape的抽象属性name和抽象方法area()perimeter()
  • 继承后,子类拥有抽象类的所有非私有成员(如printInfo()方法可直接调用)。

3. 抽象类的重写

子类不仅要实现抽象类的抽象成员,还可以重写抽象类中的具体方法具体属性,以定制化逻辑。重写时需用override关键字。

示例:重写抽象类的具体方法假设需要对RectangleprintInfo()方法扩展,增加 “是否为正方形” 的判断:

scala

scala

// 扩展Rectangle类,重写printInfo方法
class Square(side: Double) extends Rectangle(side, side) {
  // 重写name属性(矩形的name是“矩形”,正方形更改为“正方形”)
  override val name: String = "正方形"

  // 重写printInfo方法(在父类基础上增加额外信息)
  override def printInfo(): Unit = {
    super.printInfo()  // 调用父类(Rectangle)的printInfo方法
    println(s"边长:$side,是特殊的矩形")
  }
}

测试代码

scala

scala

object ShapeTest extends App {
  val circle = new Circle(5)
  circle.printInfo()  // 输出:图形:圆形,面积:78.539...,周长:31.415...

  val rect = new Rectangle(3, 4)
  rect.printInfo()    // 输出:图形:矩形,面积:12.0,周长:14.0

  val square = new Square(2)
  square.printInfo()  // 输出:
                      // 图形:正方形,面积:4.0,周长:8.0
                      // 边长:2.0,是特殊的矩形
}

重写规则

  1. 重写抽象成员(抽象属性 / 方法)时,override关键字必须添加
  2. 重写具体成员(具体属性 / 方法)时,override关键字必须添加
  3. 子类可通过super关键字调用父类的被重写方法(如super.printInfo())。
  4. 若父类方法用final修饰,则子类不能重写该方法(禁止重写)。

总结

  1. 抽象类定义:用abstract class声明,包含抽象成员(未实现)和具体成员(已实现),无法实例化。
  2. 抽象类继承:子类通过extends继承,必须实现所有抽象成员,否则子类需为抽象类。
  3. 抽象类重写:子类用override关键字重写抽象成员(必须实现)或具体成员(定制化),可通过super调用父类逻辑。

抽象类的核心作用是抽取共性、约束行为,通过继承实现代码复用和多态(如用Shape类型接收CircleRectangle实例,统一调用方法)。