You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala中如何正确重写方法?装饰器模式调用异常问题

问题分析与修复:Scala装饰器模式的方法委托错误

你代码的核心问题是装饰器没有正确将未增强的方法委托给被包装的Player实例,反而错误地在装饰器中为未增强的方法写了抛异常逻辑,导致多层包装时,未增强的方法不会调用底层被装饰对象的实现。

原代码的问题点

  1. MovementDecorator作为抽象装饰器,没有实现jump()和swim()的默认委托逻辑,导致子类必须手动实现所有方法,违背了装饰器模式的设计初衷。
  2. Jump类的swim()方法直接抛出异常,没有调用内部被包装的player_x的swim()方法——所以当你用Jump(Swim(Beginner()))创建对象后,调用swim()时执行的是Jump自己的异常逻辑,而非底层Swim实例的游泳能力。
  3. 同理,Swim类的jump()方法也是自己抛异常,没有委托给被包装对象。

修正后的代码

// 玩家接口
trait Player {
  def jump(): Unit
  def swim(): Unit
}

// 新手玩家:初始无任何能力
class Beginner extends Player {
  def jump(): Unit = throw new Error("Beginner can't jump")
  def swim(): Unit = throw new Error("Beginner can't swim")
}

// 抽象装饰器:实现默认委托逻辑
abstract class MovementDecorator(myPlayer: Player) extends Player {
  // 默认将所有方法委托给被装饰的玩家实例
  override def jump(): Unit = myPlayer.jump()
  override def swim(): Unit = myPlayer.swim()
}

// 游泳能力装饰器:只增强swim方法
class Swim(playerX: Player) extends MovementDecorator(playerX) {
  override def swim(): Unit = println("I swam!")
}

// 跳跃能力装饰器:只增强jump方法
class Jump(playerX: Player) extends MovementDecorator(playerX) {
  override def jump(): Unit = println("I jumped!")
}

测试代码与运行结果

@main
def main(): Unit = {
  val swimmer = Swim(Beginner())
  swimmer.swim() // 输出: I swam!

  val jumper = Jump(Beginner())
  jumper.jump() // 输出: I jumped!

  val swimmerJumper = Jump(Swim(Beginner()))
  swimmerJumper.jump() // 输出: I jumped!
  swimmerJumper.swim() // 输出: I swam! (现在正常工作)
}

修正逻辑说明

  1. MovementDecorator作为抽象装饰器,统一实现了Player的所有方法,默认逻辑是调用被包装对象的对应方法,子类只需要重写自己要增强的方法即可。
  2. Swim和Jump类仅重写各自负责增强的方法,其他方法自动继承抽象装饰器的委托逻辑,这样多层包装时,未增强的方法会自动穿透到底层被装饰对象的实现。

内容的提问来源于stack exchange,提问作者nowhereman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 05:35:24