从特征中定义的方法中的伴随 class 访问常量

Access a constant from the companion class inside a method defined in a trait

我创建了一个名为 Animal 的特性和两个 类,Dog 和 Cat。 Dog 和 Cat 都有同伴 类 来存储它们的生命数。我的 Cat 对象有 9 条生命,我的 Dog 对象有 1 条生命。我想向名为 isAlive 的 Animal 特征添加一个函数并在那里实现。 isAlive 函数需要访问 Animal 的存活数。我如何才能获得同伴的生命值 类?

我是否应该将生命值移至 Class 并移除同伴 类?

这是我的代码。

特质

package Animal

trait Animal {

  def speak: String

  def getDeaths: Int

  def isAlive: Boolean = {
    getDeaths < 1 // I want to replace 1 with the number of lives from the Dog or Cat
  }
}

猫 Class 和伴侣 Class

package Animal

class Cat(a: Int) extends Animal {
  private var age: Int = a
  private var deaths: Int = 0

  def this() = this(0)

  override def speak: String = {
    if (this.isAlive) {
      "Meow"
    }
    else {
      "..."
    }
  }

  // I want to do this in the trait
  // override def isAlive: Boolean = this.deaths <= Cat.lives

  def setAge(age: Int): Unit = this.age = age

  def getAge: Int = this.age

  def getDeaths: Int = this.deaths

  def die(): Unit = this.deaths += 1

}

object Cat {
  val lives: Int = 9
}

我会将 lives 作为抽象方法包含在 Animal 特征中,类似于 getDeaths(顺便说一句,Scala 不遵循 Java 的 naming conventions for getters and setters).

如果您熟悉 Java,scala 中的伴随对象类似于 Java 的 static,这意味着 objects 的类型解析发生在编译中时间,不可能像使用 class.

的方法和字段那样使用多态性

代码如下:

trait Animal {
  def speak: String
  def getDeaths: Int
  def lives: Int

  def isAlive: Boolean = {
    getDeaths < lives
  }
}


class Cat(a: Int) extends Animal {
  override val lives: Int = 9

  private var age: Int = a
  private var deaths: Int = 0

  def this() = this(0)

   /* ... */
}

或者,您可以在伴随对象中定义 lives 常量,并在覆盖 lives 方法时在具体 class 中引用它:

class Cat(a: Int) extends Animal {
  override val lives: Int = Cat.lives

  private var age: Int = a
  private var deaths: Int = 0

  def this() = this(0)

   /* ... */
}

object Cat {
  val lives = 9
}

要在 trait 中访问 lives 它必须是特征的一部分,正如@Alvean 指出的那样,或者您必须将其作为 类 扩展特性需要有它。

trait Animal { self: {val lives: Int} =>
  def isAlive: Boolean = getDeaths < lives
  . . .
}

class Cat(a: Int) extends Animal {
  val lives = Cat.lives  //required to be an Animal
  . . .
}