为什么"抽象覆盖"不要求"覆盖"在subtrait独自一人?

时间:2014-05-14 03:31:50

标签: scala traits

我阅读了Scala中编程的section,其中引入了abstract override,但我仍然对这些修饰符的加入所表示的确切含义感到困惑。使用这些修饰符的代码片段粘贴在下面:

trait Doubling extends IntQueue {
    abstract override def put(x: Int) { super.put(2 * x) }
}

特别是,我对abstract在这种情况下的目的感到困惑,以及为什么我们无法使用override关键字实现预期的结果。如果我们没有包含对super的来电,我们是否需要关键字abstract?为什么或者为什么不?我正在寻找这个关键字组合的详细解释,因为它与可堆叠特征有关。

3 个答案:

答案 0 :(得分:20)

原因是基类方法是 abstract

abstract class IntQueue {
  def get(): Int
  def put(x: Int)
}

如果你没有把abstract放在特质上,你最终会得到你想要的解释:

trait Doubling extends IntQueue {
     override def put(x: Int) { super.put(2 * x) }
}
<console>:9: error: method put in class IntQueue is accessed from
 super. It may not be abstract unless it is overridden by a member 
 declared `abstract' and `override'
            override def put(x: Int) { super.put(2 * x) }

所以 - 您需要将方法标记为abstract

这是&#34;另一方&#34;等式:如果方法确实有实现,那么就没有必要将trait的方法标记为abstract

 abstract class IntQueue {
    import collection.mutable._
        val q  =  Queue[Int]()
      def get(): Int = { q.dequeue() }
      def put(x: Int) = { q.enqueue(x) }
   }

现在不必包含abstract

 trait Doubling extends IntQueue {
        /* Look Ma! no abstract here ! */   override def put(x: Int) { super.put(2 * x) }
      }
defined trait Doubling

答案 1 :(得分:8)

这个想法是它是一个不完整的覆盖 - 你仍然希望最终具体实现特征提供该方法,即使你正在修改这个假设方法的行为。换句话说,您覆盖的方法不是一个完全独立的实现。它提供了与Python中method decorator类似的效果。

据我所知,特征上的方法是abstract override当且仅当它调用super时,它会破坏封装以期望代码的客户端检查实现知道它的方法需要具体实现。因此,您必须将其标记为abstract override以完全定义界面。

答案 2 :(得分:2)

late binding in scala traits个帖子的一部分;提供了非常明确的解释;提供了逐字逐句(请阅读full post了解更多信息):

抽象基类提供了public static void start() { int times = Integer.parseInt(n2sInput.getText()); for (int i = 0 ; i < times;i++) { yourList.add(new Random().nextInt(2000) - 1000); } } 方法的实现。这很好,因为最左边的特征调用此方法。如果基类的方法是抽象的,会发生什么?

requestApproval

如果我们更改此内容,我们会从编译器中收到一条相当奇怪的消息: 错误:访问类abstract class ApprovalRequest { def requestApproval() } 中的方法requestApproval 从超级。除非被成员覆盖,否则它可能不是抽象的 声明ApprovalRequestabstract overrideabstract的组合告诉编译器该方法的最终实现将由混合特性的类提供。如果我们将abstract关键字添加到方法中,我们就不能再使用override的匿名实现了。无法创建该对象,因为抽象覆盖方法将查找ApprovalRequest的实现,而没有一个。{1}}。相反,我们必须创建一个扩展requestApproval并实现ApprovalRequest的新类。然后我们将特征混合到该类的实例中。

requestApproval

现在将给出输出:

class ApprovalDelegate extends ApprovalRequest {
  override def requestApproval() {
    println("and now we play the waiting game")
  }
}

val adCampaign = new ApprovalDelegate with MarketingApprovalRequest
   with FinanceApprovalRequest with ExecutiveApprovalRequest