在面向对象编程中,抽象类(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)
}
说明:
- 子类
Circle和Rectangle必须用override关键字实现Shape的抽象属性name和抽象方法area()、perimeter()。 - 继承后,子类拥有抽象类的所有非私有成员(如
printInfo()方法可直接调用)。
3. 抽象类的重写
子类不仅要实现抽象类的抽象成员,还可以重写抽象类中的具体方法或具体属性,以定制化逻辑。重写时需用override关键字。
示例:重写抽象类的具体方法假设需要对Rectangle的printInfo()方法扩展,增加 “是否为正方形” 的判断:
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,是特殊的矩形
}
重写规则:
- 重写抽象成员(抽象属性 / 方法)时,
override关键字必须添加。 - 重写具体成员(具体属性 / 方法)时,
override关键字必须添加。 - 子类可通过
super关键字调用父类的被重写方法(如super.printInfo())。 - 若父类方法用
final修饰,则子类不能重写该方法(禁止重写)。
总结
- 抽象类定义:用
abstract class声明,包含抽象成员(未实现)和具体成员(已实现),无法实例化。 - 抽象类继承:子类通过
extends继承,必须实现所有抽象成员,否则子类需为抽象类。 - 抽象类重写:子类用
override关键字重写抽象成员(必须实现)或具体成员(定制化),可通过super调用父类逻辑。
抽象类的核心作用是抽取共性、约束行为,通过继承实现代码复用和多态(如用Shape类型接收Circle、Rectangle实例,统一调用方法)。