1
votes

Assuming I have a simple abstract base class like so:

abstract class MyAbstractBaseClass { 
    def hello : Unit 
}

and then I write a "stacking" trait like so:

trait MyTrait extends MyAbstractBaseClass { 
    abstract override def hello : Unit = 
    { 
        super.hello             
        println("How are you?"); 
    }
}

then why won't Scala let me define a subclass as follows:

class MyClass extends MyAbstractBaseClass with MyTrait {
    override def hello : Unit = println("Hello!")
}

error: overriding method hello in trait MyTrait of type => Unit;
 method hello needs `abstract override' modifiers

If I try their suggestion of using 'abstract override':

class MyClass extends MyAbstractBaseClass with MyTrait {
    abstract override def hello : Unit = println("Hello!")
}

error: `abstract override' modifier only allowed for members of traits

Can anyone help me understand this?

P.S. I know that the below does work:

class MyClass extends MyAbstractBaseClass {
   override def hello : Unit = println("Hello!")
}

val x = new MyClass with MyTrait
x.hello

Hello!
How are you?

but am trying to understand why the former does not.

In summary: why can't I provide an implementation of the abstract base class - while also taking advantage of the trait's functionality?

1
"abstract override' modifier only allowed for members of traits" + "error: abstract override' modifier only allowed for members of traits" = you can't override abstractly overriden methods inside a classdk14
Thanks @dk14, it makes sense to me that I can't use 'abstract override'. What I don't understand is why I can't provide an implementation of the abstract base class - while also taking advantage of the trait's functionality?Tom G
What if you remove the override keyword in your MyClass definition (in your block number 3 on the post). You can't override (from MyClass) a trait's method that is marked abstract override. The last block is valid since your stackable stack with traits is made after a valid compilation of MyClass.Mik378
@Mik378: then I get error: overriding method hello in trait MyTrait of type => Unit; method hello needs `override' modifierTom G
Can you post the code you changed here?Mik378

1 Answers

2
votes

The trick is that you can't have an "abstract" method in the flow of the linearization, that is called from a super call.

Try this, you will see it compiles:

abstract class MyAbstractBaseClass {
  def hello : Unit
}

class SubClass extends MyAbstractBaseClass {
  def hello {
    println("toto")
  }
}


trait MyTrait extends MyAbstractBaseClass {
  abstract override def hello : Unit =
  {
    super.hello
    println("How are you?")
  }
}

class MyClass extends SubClass with MyTrait {  //note the CONCRETE SubClass here
  override def hello : Unit = println("Hello!")
}

new MyClass().hello

You got the error, because the compiler starts with MyTrait (at the top of the stack, so the first to be called) and that MyTrait calls through super an abstract method... (of MyAbstractBaseClass) => it crashes since your super call can't target immediately a concrete method.

In my code snippet, you will notice that MyTrait is "at the top" (during linearization) of a concrete Subclass class, that makes the trick.