1

I have a method in my trait

def controller: AnyRef

but my concrete class was not implementing that method and it was still compiling. The compiler doesn't let me add abstract to that method either. How can I create a method in a trait that forces it's implementer to implement it?

thanks, Dean

Dean Hiller
  • 19,235
  • 25
  • 129
  • 212
  • Is the class extending your trait abstract? – Johnny Everson Sep 04 '14 at 11:53
  • yes, and I figured it out. in the concrete subclass, there was a val controller = new Controller and when that happens, for some reason, calling controller in the trait method ends up returning null. I added the true answer below(but then have a new question as to why it compiles) – Dean Hiller Sep 08 '14 at 16:41

3 Answers3

6

The compiler enforces that concrete classes implement all the abstracts methods they inherit from superclasses and traits.

If your class was compiling it meant it wasn't concrete, i.e. it was a trait or an abstract class, and you can't force neither to implement the abstract method.

Of course, as soon as you try to obtain a concrete instance the compiler will raise an error as the method is not implemented.

Practical example in the REPL

scala> trait A { def controller: AnyRef }
defined trait A

scala> trait B extends A
defined trait B

scala> abstract class C extends A
defined class C

scala> class D extends A
<console>:8: error: class D needs to be abstract, since method controller in trait A of type => AnyRef is not defined
       class D extends A

scala> new B { }
<console>:10: error: object creation impossible, since method controller in trait A of type => AnyRef is not defined
              new B { }
                  ^

scala> new C
<console>:10: error: class C is abstract; cannot be instantiated
              new C
Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
  • ah, I could have sworn I had that compiling with abstract method and running and it returned null in my case but for some reason today I cannot reproduce it :(. – Dean Hiller Sep 08 '14 at 16:38
  • I can reproduce it now. In the concrete subclass there was a val controller = new TheController() and in this case, the trait ends up returning null when you call controller in that case. This seems like a scala bug or something. – Dean Hiller Sep 08 '14 at 16:40
  • it's probably an order of initialization issue. You should open a new question for that specific problem, with a minimum reproducible example – Gabriele Petronella Sep 08 '14 at 17:01
1

If you are not getting any compilation error for such case, I think your IDE has some problem, try refresh/clean your project.

If your trait has implementation of "controller" function, then the concrete class(non abstract class) extending trait need not have any implementation for "controller" function. That's the beauty of trait in Scala, not forcing all the concrete class to implement some common methods with same implementation.

user3366706
  • 1,529
  • 3
  • 31
  • 54
  • turns out if you have concrete subclass with val controller= new Controller, it compiles!!! and worse, it returns null instead of the controller. – Dean Hiller Sep 08 '14 at 17:30
0

well, there seems to be some weird scala issue occuring.

When you have a concrete subclass that has a

val controller = new Controller

it seems to affect the traits controller and having your trait call controller results in null being returned. Everything compiles just fine (though I think that might be a scala bug as I don't 'think' that should actually compile).

If it should compile, then can someone please explain why it compiles.

Dean Hiller
  • 19,235
  • 25
  • 129
  • 212