繁体   English   中英

Scala:如何对内部案例类的封闭对象进行模式匹配?

[英]Scala: How to pattern-match the enclosing object of an inner case class?

我有一个内部案例类,特别是这个问题的一个事件,并且想要匹配它,包括外部对象:

class Player {
  var _life = 20
  def life = _life

  def gainLife(life: Int) = execute(GainLife(life))

  case class GainLife(life: Int) extends Event {
    def execute() = _life += life
  }
}

我可以轻松编写一个效果(部分功能)来替换特定玩家的生活事件:

//gain twice as much life
def effect(player: Player): ReplacementEffect = {
  case player.GainLife(x) => player.GainLife(x * 2)
}

但是,我不能为其他玩家做同样的事情。 我最接近的是:

//only you gain life
def effect2(player: Player): ReplacementEffect = {
  case evt: Player#GainLife => player.GainLife(evt.life)
}

但是1)这甚至用新的生命值代替了您自己的生命值; 2)我无法参照最初在该功能中获得生命值的玩家; 3)我错过了以这种方式直接匹配life

这可以使用与路径无关的类型表示,例如

case Player.GainLife(_player, life) if _player != player => GainLife(player, life)

理想情况下,我想要类似

case _player.GainLife(life) if _player != player => player.GainLife(life)

是否可能以某种方式解决此问题,或者我可以解决此问题? 还是我不得不求助于GainLife的嵌套?

当您在另一个类中定义类时,这意味着该类型特定于周围的类,因此,如果您希望PlayerA.GainLife表示相同的内容,则它与playerB.GainLife是不同的类型(称为路径依赖类型)。您可以在相同的范围内定义它,而不管实例如何:类的包或伴随对象。

您可以在以下问题中了解更多信息: Scala的依赖于路径的类型是什么意思?

我来最接近的是确定自己unapply方法:

class Player {
  self =>

  var _life = 20
  def life = _life

  def gainLife(life: Int) = execute(GainLife(life))

  case class GainLife(life: Int) extends Event {
    def player = self

    def execute() = _life += life
  }
}

object Player {
  object _GainLife {
    def unapply(event: Player#GainLife) =
      Some((event.player, event.life))
  }
}

请注意,命名Player._GainLife对象Player.GainLife会引起名称冲突,这是这里最重要的缺点。 因此,我选择从Player命名空间之外使该类型可用:

val GainLife = Player._GainLife

这允许以简洁的方式同时使用player.GainLife.unapply和Player._GainLife.unapply进行匹配:

//gain twice as much life
def effect1(player: Player): ReplacementEffect = {
  case player.GainLife(life) => player.GainLife(life * 2)
}

//only you gain life
def effect2(player: Player): ReplacementEffect = {
  case GainLife(_player, life) if _player != player => player.GainLife(life)
}

//all players gain twice as much life
def effect3: ReplacementEffect = {
  case GainLife(player, life) => player.GainLife(life * 2)
}

最后两个示例看起来有点不对称,但是可以根据需要使用apply方法修复。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM