1 class 继承
为了提高代码的重用性,提高开发效率,Scala 的 class
是支持继承的。
Scala 的继承与 Java 的继承非常类似:
(1) 单继承:
类似于 Java,Scala 也只支持单继承,一个类只能直接继承自一个父类。这意味着一个 Scala 类可以拥有一个直接的父类,就像 Java 中一样。
(2) 继承语法:
Scala 的继承语法类似于 Java,使用 extends 关键字来继承一个父类。例如:
scala
class ChildClass extends ParentClass {
// 子类的定义
}
(3) 重写方法:
Scala 和 Java 都允许子类覆盖父类中的方法,通过使用 override 关键字来标记。例如:
scala
class ChildClass extends ParentClass {
override def someMethod(): Unit = {
// 子类重写父类的方法
}
}
(4) 调用父类方法:
在 Scala 中,使用 super 关键字来调用父类的方法。例如:
scala
class ChildClass extends ParentClass {
override def someMethod(): Unit = {
super.someMethod() // 调用父类的方法
// 子类的其他逻辑
}
}
下面定义了足球员类 FootballPlayer
,及它的子类,进攻球员类 Striker
,防守球员类 Defender
:
scala
/**
* 足球员父类
*
* @param name 球员姓名
*/
class FootballPlayer(val name: String) {
def play(): String = "Playing football"
}
/**
* 进攻球员子类
*
* @param name 球员姓名
*/
class Striker(name: String) extends FootballPlayer(name) {
override def play(): String = "Scoring goals" // 重写父类的 play 方法
def celebrate(): String = s"$name is celebrating"
}
/**
* 防守球员子类
* @param name 球员姓名
*/
class Defender(name: String) extends FootballPlayer(name) {
override def play(): String = "Defending the goal" // 重写父类的 play 方法
def tackle(): String = s"$name is making a tackle"
}
object App {
def main(args: Array[String]): Unit = {
// 测试
val striker = new Striker("Ronaldo")
println(striker.play()) // 输出 Scoring goals,调用重写后的 play 方法
println(striker.celebrate()) // 输出 Ronaldo is celebrating,调用子类的 celebrate 方法
val defender = new Defender("Sergio Ramos")
println(defender.play()) // 输出 Defending the goal,调用重写后的 play 方法
println(defender.tackle()) // 输出 Sergio Ramos is making a tackle,调用子类的 tackle 方法
}
}
运行程序,控制台输出:
markdown
Scoring goals
Ronaldo is celebrating
Defending the goal
Sergio Ramos is making a tackle
2 抽象类
在 Scala 中,抽象类是一种不能被实例化的类,它们通常用于定义一些通用的行为,但又需要子类来提供具体实现的情况。
scala
/**
* 足球员抽象类
* @param name 球员姓名
*/
abstract class FootballPlayer(val name: String) {
/**
* 抽象方法,没有具体实现
* @return
*/
def play(): String
}
/**
* 定义实现类 Striker 继承自抽象类 FootballPlayer
* @param name 球员姓名
*/
class Striker(name: String) extends FootballPlayer(name) {
// 实现抽象方法 play
def play(): String = s"$name is scoring goals"
}
/**
* 定义实现类 Defender 继承自抽象类 FootballPlayer
* @param name 球员姓名
*/
class Defender(name: String) extends FootballPlayer(name) {
// 实现抽象方法 play
def play(): String = s"$name is defending the goal"
}
object App {
def main(args: Array[String]): Unit = {
// 定义进攻球员对象
val striker = new Striker("Ronaldo")
println(striker.play()) // 输出 Ronaldo is scoring goals
// 定义防守球员对象
val defender = new Defender("Sergio Ramos")
println(defender.play()) // 输出 Sergio Ramos is defending the goal
}
}
上面的例子中:
FootballPlayer
类是一个抽象类,包含一个抽象方法play
,没有具体的实现。Striker
类和Defender
类是抽象类FootballPlayer
的实现类,它们都实现了play
方法,并提供了具体的实现。- 在测试部分,创建了一个
Striker
对象和一个Defender
对象,并分别调用它们的play
方法。
运行代码,控制台输出:
markdown
Ronaldo is scoring goals
Sergio Ramos is defending the goal
3 特质
3.1 特质介绍
Trait
(特质)是 Scala 中一种非常有用的机制,可以用于定义对象的特定特征或行为。Trait
类似于 Java 中的接口。
Trait
与 抽象类
是不同的:
Trait
可以被多重继承,一个类可以扩展多个Trait
,但只能继承一个抽象类。Trait
不能接受构造参数,但抽象类可以。Trait
与 抽象类 的语义不同,Trait
更适合描述对象的特征或行为,以及对象之间的has-a
或can-do
关系。抽象类更适合描述is-a
关系,即子类是父类的一种特定类型。
下面是一个使用特质的例子:
scala
/**
* 定义一个球员类
*
* @param name 球员姓名
*/
class FootballPlayer(val name: String)
/**
* 声明一个奔跑 trait
*/
trait Runner {
def run(name: String): String = s"${name} is running"
}
/**
* 声明一个得分手 trait
*/
trait Scorer {
def score(name: String): String = s"${name} is scoring goals"
}
/**
* 声明一个防守人员 trait
*/
trait Defender {
def defend(name: String): String = s"${name} is defending"
}
/**
* 创建实现类,同时继承三个 Trait
*
* @param name 球员姓名
*/
class Player(name: String) extends FootballPlayer(name) with Runner with Scorer with Defender
object App {
def main(args: Array[String]): Unit = {
// 测试
val player = new Player("Messi")
// 输出 Player is running
println(player.run(player.name))
// 输出 Player is scoring goals
println(player.score(player.name))
// 输出 Player is defending
println(player.defend(player.name))
}
}
上面的例子中:
- 定义了一个
FootballPlayer
类,它具有一个name
属性,用于表示足球球员的姓名。 - Runner
Trait
包含一个run
方法,表示球员奔跑的行为。 - Scorer
Trait
包含一个score
方法,表示球员进球的行为。 - Defender
Trait
包含一个defend
方法,表示球员防守的行为。 - 创建了一个名为
Player
的实现类,它继承了FootballPlayer
类,并且同时混入了Runner
、Scorer
和Defender
三个Trait
。 - 在测试部分,创建了一个名为
player
的Player
实例,并调用了它的run
、score
和defend
方法,展示了实现类获得了这三个Trait
中定义的行为。
3.2 对象混入特质
在 Scala 中,对象混入(Mixins
)Trait
是一种非常强大和灵活的特性,它允许对象在运行时获得 Trait
中定义的行为,而无需继承 Trait
的类。对象混入 Trait
的过程就是 将 Trait 中定义的方法和属性动态地添加到对象中。
混入 Trait
可以为对象提供额外的功能,而无需改变其类层次结构。这种灵活性使得在 Scala 中,对象可以非常容易地适应不同的需求,同时保持代码的简洁和可维护性。
scala
/**
* 定义队长特质
*/
trait Captain {
/**
* 标识是否为队长
*/
var isCaptain: Boolean = false
/**
* 判断 isCaption,输出是否为队长
*/
def hello(): Unit = {
if (isCaptain) println("I am caption") else println("I am not caption")
}
}
/**
* 球员类
* @param name 球员姓名
*/
class FootballPlayer(val name: String)
object App {
def main(args: Array[String]): Unit = {
// 实例化 FootballPlayer 时,让对象同时拥有 Captain 的相关属性、方法
val player = new FootballPlayer("Ronaldo") with Captain
player.isCaptain = true
player.hello()
}
}
在这个例子中,使用 对象混入特质
的方式,给 FootballPlayer
对象添加了队长属性。这使得我们可以非常灵活地为对象添加额外的功能,而无需修改类的层次结构。