在面向对象编程中,多继承是一个经典需求 —— 一个类需要具备多个不同来源的属性和方法。但传统多继承会带来菱形继承等问题,而 Scala 中的特质(trait)恰好提供了一种灵活、安全的解决方案。
一、特质是什么?
特质(trait)是 Scala 中用于实现代码复用和多继承的核心语法结构,类似 Java 8+ 的接口(但功能更强大)。可以把它理解为:一组可以被多个类共享的属性和方法集合,类通过「混入(with)」特质来获得这些能力。
二、特质的核心语法:抽象与具体成员
特质中的成员(属性 / 方法)分为「抽象」和「具体」两类,区分规则非常简单:
- 具体成员:有初始值(属性带
=赋值)或有方法体(方法带{}实现) - 抽象成员:无初始值(属性仅声明类型)或无方法体(方法仅声明签名),必须由混入的类实现
实例:定义两个独立特质
我们通过两个特质模拟「漂亮眼睛」和「高挑身材」两种能力,包含不同类型的成员:
package level02
/* 特质
* trait: 实现多继承(混入多个特质)
* 具体属性和抽象属性 怎么区分?
* 有具体值的(带 = 赋值),就是具体属性;无具体值(只声明类型),就是抽象属性
*/
object class15 {
// 独立特质1:包含具体属性、抽象属性、抽象方法
trait BeautifulEye {
val beautifulGuy = "超级漂亮" // 具体属性(带 =)
val name: String // 抽象属性(无 =,只声明类型)
def jump(): Unit // 抽象方法(无方法体,必须由子类实现)
}
// 独立特质2:包含具体属性、具体方法
trait Tall {
val height: String = "太高" // 具体属性
var weight: Int = 0 // 具体属性(var 可变)
def run(): Unit = { // 具体方法(有方法体)
println("run...")
}
}
// 子类:混入两个独立特质,实现抽象属性和抽象方法
class Child extends BeautifulEye with Tall {
override val name: String = "小记"
override def jump(): Unit = {
println(s"$name, jump...")
}
}
// 主方法(程序入口)
def main(args: Array[String]): Unit = {
val child = new Child()
println(child.name)
println(child.height)
println(child.beautifulGuy)
child.run()
child.jump()
}
}