如何在 Scala 中表示内部单例

How to denote an inner singleton in Scala

为了锻炼我在 Scala 特定功能上的 OOP 能力,我尝试设计一个游戏,其中我有 Player class。它有一个抽象方法 play,它决定给定玩家列表(不同于调用该方法的玩家)采取什么行动。我想阻止 play 方法改变其他玩家的状态。正确的玩法是施放Spell,让系统将其效果反映到其他玩家身上。

然而,play 方法需要其他玩家的读取权限来决定策略。因此,我创建了一个内部单例 ReadOnlyPlayer。我将其设为单例以防止一遍又一遍地复制,并且每次都简单地 returning 这个单例。

abstract class Player(private var _health: Int = 0) {
    Check.isPositive(_health)

    def health = _health

    def play(players: List[/*?*/]) // how to denote inner type ReadOnlyPlayer ?

    def hit(damage: Int) = { _health = max(0, _health - damage); this }

    def safeCopy = ReadOnlyPlayer

    final object ReadOnlyPlayer extends Player {
        override def health = _health

        // noop
        override def hit (damage: Int  ) = this
        override def play(players: List[/*?*/]) = ()
    }
}

由于我添加评论的行,我无法编译它。我知道有许多解决此问题的方法:

我知道如何以各种方式处理这个问题,所以我的问题更多是出于好奇:如何表示内部单例类型?

请注意,我在回答时并没有完全理解您要做什么来制作内部单例列表。

通常使用SingletonName.type访问单例类型。所以,在你的情况下,它看起来像这样:

abstract class Player(private var _health: Int = 0) {

  def health = _health

  def play(players: List[ReadOnlyPlayer.type]) = ()// how to denote inner type ReadOnlyPlayer ?

  def hit(damage: Int) = { _health = Math.max(0, _health - damage); this }

  def safeCopy = ReadOnlyPlayer

  final object ReadOnlyPlayer extends Player {
    override def health = _health

    // noop
    override def hit (damage: Int  ) = this
    override def play(players: List[ReadOnlyPlayer.type]) = ()
  }
}

正如@lloydme 指出的那样,我试图实现的目标没有任何意义。这是我最终选择的解决方案:

sealed trait ReadOnlyPlayer extends Player

abstract class Player(private var _health: Int = 0) {
    Check.isPositive(_health)

    def health = _health

    def play(players: List[ReadOnlyPlayer])

    def hit(damage: Int) = { _health = max(0, _health - damage); this }

    lazy val safeCopy: ReadOnlyPlayer = ReadOnlyCopy

    private object ReadOnlyCopy extends ReadOnlyPlayer {
        override def health = _health

        // noop
        override def hit (damage: Int) = this
        override def play(players: List[ReadOnlyPlayer]) = ()
    }
}

嵌套对象列表:

$ scala
Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_60).
Type in expressions to have them evaluated.
Type :help for more information.

scala> class X(id: Int) { object Y { def y = id } }
defined class X

scala> val xs = List.tabulate(10)(new X(_))
xs: List[X] = List(X@5f77d0f9, X@463fd068, X@895e367, X@1b266842, X@7a3793c7, X@42b3b079, X@651aed93, X@4dd6fd0a, X@bb9e6dc, X@5456afaa)

scala> val Ys = xs map (_.Y)
Ys: List[x.Y.type forSome { val x: X }] = List(X$Y$@43c67247, X$Y$@fac80, X$Y$@726386ed, X$Y$@649f2009, X$Y$@14bb2297, X$Y$@69adf72c, X$Y$@797501a, X$Y$@1a15b789, X$Y$@57f791c6, X$Y$@51650883)

scala> val ys = Ys map (_.y)
ys: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)