6

I have a trait I (intermediary), a class M (mixer) mixing in the trait and a trait S (specific).

class M extends Something with S {
    def baz() = foo()
}

trait I {
    def foo(): { ...; bar(); ... }
    def bar()
}

trait S extends I {
    def bar() = 42
}

I serves as an intermediate layer between M and S, providing a common interface.

I have an implemented method foo in I that calls a method bar (not implemented in I but defined there). What I would like to achieve is that all traits extending I must implement bar, so that this would throw a compile time error because bar is not implemented:

trait Z extends I

Is this possible in Scala?

P.S.: I am aware of the answer of Force Scala trait to implement a certain method but I do not want that kind of explicit coupling.

Community
  • 1
  • 1
tobi
  • 81
  • 6
  • You can't force a `trait` to implement something like that. – Dave L. Oct 22 '13 at 14:01
  • 1
    I'm curious, why do you need that? You'll get your compile error as soon as you try to have a concrete implementation of I (forcing you to provide a def bar). But a trait is by essence abstract... – Guillaume Oct 22 '13 at 14:28
  • I need it because the traits and the concrete implementation live in separate software packages. The traits are in a library that has no concrete usages of these traits. I could test for the correct implementation of these traits in my test suite. I would like it better, however, if the errors would already pop up at compile time (e.g. in my IDE). – tobi Oct 22 '13 at 15:11

3 Answers3

1

I thought about structural subtyping:

trait I[T<: { def:foo:Unit}]

....

would that work for you?

Stefan Kunze
  • 741
  • 6
  • 15
  • 1
    Is this what you have in mind? `class M extends Object with S { def baz() = foo() } trait I[T <: { def bar(): Unit }] { def foo() { bar() } def bar() } trait S extends I[S] { def bar() = 42 }` Because if so, then something like `trait Q extends I[Q] { }` still does not throw a compile time error. – tobi Oct 24 '13 at 11:13
  • yeah I thought sth like that. – Stefan Kunze Oct 24 '13 at 14:41
1

It seems a use case for self types :

trait Z {
   self : I =>
}

The compiler will check that any class in a hierarchy including Z is or extends I.

Yann Moisan
  • 8,161
  • 8
  • 47
  • 91
  • Could you please add an example? I don't see how I get compile time errors out of it if `trait Z` does not define `bar()`. – tobi Oct 30 '13 at 08:50
  • I think with self types it is still not possible to force a **trait** to implement a certain method. The compiler will throw an error if a **class** uses `trait Z` and `Z` did not provide an implementation. But as I said in a [previous comment](http://stackoverflow.com/questions/19513843/force-trait-to-implement-method#comment28960874_19513843), I would like to catch the error earlier. – tobi Nov 01 '13 at 07:56
0

I don't know of any way in Scala to force a trait to have concrete implementations for all methods. You could write a macro that generated a small test class and then the compiler would verify that the test class was concrete. It shouldn't be too hard to write a macro that takes this code:

@VerifyAllMethodsConcrete
trait Z extends I { ... }

and transforms it into this code:

trait Z extends I { ... }
class TestClassForVerifyingConcreteMethodsOfZ { }

Now if trait Z does not override bar() there will be an early error that says TestClassForVerifyingConcreteMethodsOfZ needs to be abstract. This error message isn't perfectly clear but hopefully this does the early verification on Z that you want.

Kevin2342
  • 51
  • 6