【问题标题】:Access a constant from the companion class inside a method defined in a trait从特征中定义的方法内的伴随类访问常量
【发布时间】:2018-03-02 23:14:32
【问题描述】:

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

我应该只是将生命值移入类并删除伴随类吗?

这是我的代码。

特质

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
  }
}

猫类和同伴类

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
}

【问题讨论】:

    标签: scala oop traits


    【解决方案1】:

    我会将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 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
    }
    

    【讨论】:

      【解决方案2】:

      要在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
        . . .
      }
      

      【讨论】:

      • 请注意,此声明 self: {val lives: Int} =&gt; 使 lives 成为通过反射调用调用的方法。它可能会导致实际应用中的性能欠佳。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多