Why is "abstract override" required not "override" alone in subtrait?

The reason is that the base class method is abstract

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

If you were to not put abstract on the trait you end up with the explanation you were seeking:

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

So - you would need to mark the method as abstract.

Here is the "other side" of the equation: if the methods do have implementations then it is not necessary to mark the trait's method as abstract:

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

It is now unnecessary to include abstract

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

The idea is that it's an incomplete override -- you still want to require the eventually concrete implementation of the trait to provide that method, even though you're modifying that hypothetical method's behavior. In other words, the method you're overriding isn't a full standalone implementation. It gives a similar effect as a method decorator might in Python.

As far as I can reason, a method on a trait is abstract override if and only if it calls super, but it breaks encapsulation to expect the client of the code to inspect the implementation of the method to know it needs a concrete implementation. Therefore, you must mark it abstract override to fully define the interface.


A part of late binding in scala traits posts; provides a very clear explanation; provided verbatim bellow (read the full post for more info):

The abstract base class provided an implementation of the requestApproval method. This is good since the leftmost trait calls this method. What happens if the base class’s method is abstract?

abstract class ApprovalRequest {
  def requestApproval()
}

If we change this, we get a rather odd message from the compiler: error: method requestApproval in class ApprovalRequest is accessed from super. It may not be abstract unless it is overridden by a member declared abstract and override The combination of abstract and override tells the compiler that the final implementation of the method will be provided by the class mixing-in the trait. If we add the abstract keyword to the methods, we can no longer use our anonymous implementation of ApprovalRequest. That object can’t be created since the abstract override methods will be looking for an implementation of requestApproval and there isn’t one. Instead we have to create a new class that extends ApprovalRequest and implements requestApproval. We then mix the traits into an instance of that class.

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

Which will now give the output:

requesting approaval from executives
requesting approval from Finance
requesting approval from Marketing
and now we play the waiting game

Tags:

Scala

Traits