9 scala的类继承及trait

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-acan-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 类,并且同时混入了 RunnerScorerDefender 三个 Trait
  • 在测试部分,创建了一个名为 playerPlayer 实例,并调用了它的 runscoredefend 方法,展示了实现类获得了这三个 Trait 中定义的行为。

3.2 对象混入特质

在 Scala 中,对象混入(MixinsTrait 是一种非常强大和灵活的特性,它允许对象在运行时获得 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 对象添加了队长属性。这使得我们可以非常灵活地为对象添加额外的功能,而无需修改类的层次结构。

相关推荐
向宇it40 分钟前
【从零开始入门unity游戏开发之——C#篇26】C#面向对象动态多态——接口(Interface)、接口里氏替换原则、密封方法(`sealed` )
java·开发语言·unity·c#·游戏引擎·里氏替换原则
@菜鸟进阶记@43 分钟前
java根据Word模板实现动态填充导出
java·开发语言
卖芒果的潇洒农民1 小时前
Lecture 6 Isolation & System Call Entry
java·开发语言
SomeB1oody1 小时前
【Rust自学】6.1. 定义枚举
开发语言·后端·rust
SomeB1oody1 小时前
【Rust自学】5.3. struct的方法(Method)
开发语言·后端·rust
Kisorge2 小时前
【C语言】指针数组、数组指针、函数指针、指针函数、函数指针数组、回调函数
c语言·开发语言
啦啦右一3 小时前
Spring Boot | (一)Spring开发环境构建
spring boot·后端·spring
森屿Serien3 小时前
Spring Boot常用注解
java·spring boot·后端
轻口味3 小时前
命名空间与模块化概述
开发语言·前端·javascript
晓纪同学4 小时前
QT-简单视觉框架代码
开发语言·qt