jeudi 15 décembre 2022

How to properly override a method in Scala?

I'm exercising the decorator design pattern in Scala. I have the following implementation of a "Player".

// interface for the player
trait Player {
  def jump(): Unit
  def swim(): Unit
}

// a beginner player can't jump nor swim
class Beginner extends Player {
  def jump(): Unit = throw Error()
  def swim(): Unit = throw Error()
}

// movement decorator abstraction
abstract class MovementDecorator(my_player: Player) extends Player {
}

// concrete decorator
class Swim(player_x: Player) extends MovementDecorator(player_x) {
  def jump(): Unit = throw new Error("I can't jump")
  override def swim(): Unit = println("I swam!")
}

// concrete decorator
class Jump(player_x: Player) extends MovementDecorator(player_x) {
  override def jump(): Unit = println("I jumped!")
  def swim(): Unit = throw new Error("I can't swim")
}

A concrete Player (i.e. Beginner) can't have moves such as jump() or swim(). But I can decorate aka wrap the object with the Swim and/or Jump classes to give the Beginner that capability.

However, when I run the main method, I get the outputs shown with comments.

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

  val jumper = Jump(Beginner())
  jumper.jump() // "I jumped!"

  val swimmer_jumper = Jump(Swim(Beginner()))
  swimmer_jumper.jump() // "I jumped!"
  swimmer_jumper.swim() // Exception at Jump.swim: I can't swim
}

I want to keep the following to create my object

val swimmer_jumper = Jump(Swim(Beginner()))

Is there a specific way of overriding methods that I'm missing? I thought when you override a method it overrides any other method of the object -- and it becomes the preferred one.

Any help would be appreciated!

Aucun commentaire:

Enregistrer un commentaire