一、Scala 类继承的基础规则
Scala 中的类继承和 Java 有相似之处,但也有自己的特点:
- 默认不可继承:Scala 中普通类默认是
final的(不可继承),必须用class 类名前加open关键字才能被继承(Scala 3);Scala 2 中需要显式去掉final或用sealed限制继承范围。 - 继承语法:使用
extends关键字,格式为class 子类 extends 父类。 - 构造器调用:子类构造器会优先调用父类的主构造器,若要调用父类辅助构造器,需在子类构造器中显式处理。
- 方法重写:重写父类方法必须用
override关键字(强制要求,避免误写)。
二、基础示例:简单类的继承
1. Scala 3 版本(推荐)
// 父类:用 open 标记可继承
open class Person(val name: String, val age: Int) {
// 父类方法
def introduce(): String = s"我叫$name,今年$age 岁"
// 辅助构造器
def this(name: String) = this(name, 0)
}
// 子类:继承 Person
class Student(name: String, age: Int, val studentId: String) extends Person(name, age) {
// 重写父类方法,必须加 override
override def introduce(): String = s"我叫$name,今年$age 岁,学号是$studentId"
// 子类独有方法
def study(): Unit = println(s"$name 正在学习")
}
// 测试代码
object InheritDemo extends App {
val student = new Student("张三", 18, "2024001")
println(student.introduce()) // 输出:我叫张三,今年18岁,学号是2024001
student.study() // 输出:张三正在学习
// 父类引用指向子类对象(多态)
val person: Person = new Student("李四", 19, "2024002")
println(person.introduce()) // 输出:我叫李四,今年19岁,学号是2024002
}
2. Scala 2 版本(无 open 关键字)
// Scala 2 中无需 open,默认可继承(除非加 final)
class Person(val name: String, val age: Int) {
def introduce(): String = s"我叫$name,今年$age 岁"
def this(name: String) = this(name, 0)
}
class Student(name: String, age: Int, val studentId: String) extends Person(name, age) {
override def introduce(): String = s"我叫$name,今年$age 岁,学号是$studentId"
def study(): Unit = println(s"$name 正在学习")
}
object InheritDemo extends App {
val student = new Student("张三", 18, "2024001")
println(student.introduce())
}
三、关键知识点详解
1. 构造器的继承规则
-
子类主构造器的参数会自动传递给父类主构造器(如
extends Person(name, age))。 -
若父类没有无参主构造器,子类必须显式调用父类的有参构造器,否则编译报错。
-
示例:父类只有有参构造器时,子类的写法
open class Person(name: String) { // 父类主构造器有参 val fullName = name } // 子类必须显式传参给父类构造器 class Student(name: String, id: String) extends Person(name) { val studentId = id }
2. 方法重写
-
必须加
override关键字(Scala 强制要求,Java 是可选)。 -
若父类方法是
final,子类无法重写。 -
可以重写
val字段(本质是重写字段的 getter 方法):open class Person { val info: String = "父类信息" } class Student extends Person { override val info: String = "子类信息" // 重写字段 }
3. 抽象类的继承
Scala 中抽象类用 abstract 修饰,包含抽象方法 / 字段(无实现),子类必须实现抽象成员:
// 抽象父类
abstract class Shape {
// 抽象方法(无实现)
def area(): Double
// 抽象字段(无初始值)
val color: String
}
// 子类实现抽象成员
class Circle(val radius: Double) extends Shape {
override def area(): Double = Math.PI * radius * radius
override val color: String = "red"
}
object ShapeDemo extends App {
val circle = new Circle(2.0)
println(circle.area()) // 输出:12.566370614359172
println(circle.color) // 输出:red
}
4. 单继承限制
和 Java 一样,Scala 类只能单继承(一个子类只能有一个直接父类),但可以通过 trait(特质)实现类似多继承的效果。
四、总结
- 核心语法:Scala 3 中父类需加
open才能被继承,子类用extends关键字,重写方法 / 字段必须加override。 - 构造器规则:子类构造器必须显式调用父类构造器(若父类无无参构造器),参数通过
extends 父类(参数)传递。 - 关键特性:Scala 支持抽象类继承、字段重写,且强制
override关键字,避免误重写,同时遵循单继承原则(可结合 trait 补充多继承能力)。