Implement keyword (instead of override)

I don’t think that should be legal for the same reason that it’s illegal without the implements:

scala> :pa -raw
// Entering paste mode (ctrl-D to finish)

trait A { def name: String }
trait B extends A { def name = "Alice" }
trait C extends A { def name = "Bob" }
class D extends B with C

// Exiting paste mode, now interpreting.


class D extends B with C
      ^
<pastie>:4: error: class D inherits conflicting members:
  def name: String (defined in trait B) and
  def name: String (defined in trait C)
  (note: this can be resolved by declaring an `override` in class D.)
There were compilation errors!
3 Likes

Something like that?

Parent Modifier Outcome
abstract override compile error
abstract implement ok
abstract none compile error
concrete override ok
concrete implement compile error
concrete none compile error
absent override compile error
absent implement compile error
absent none ok
4 Likes

how about

Parent\Modifier none implement override
absent OK warn error
abstract warn OK warn
concrete error warn OK

?

4 Likes

Yeah sorry your layout makes more sense - I tend to use decision tables by default because I can then automatically turn them in property based tests, but that made little sense here.

I’m personally not very fussed about the distinction between warn and error - all my builds have fatal warnings enabled. I’m not 100% sure I see the logic though: what makes you go from warning to error? In the first line, for example, both “bad” cases feel equally bad (or benign) to me.

2 Likes

Oh, that’s wonderful. Thank you and @nrinaudo for outlining it.

For comparison this is what the situation is today, in Scala 2:

Parent\Modifier none implement override
absent OK (n/a) error
abstract OK (n/a) OK
concrete error (n/a) OK

To me the symmetry is very compelling! Both that:

  • there is a missing modifier in the language, and
  • the grey warning barrier between the OK states and the error states.
6 Likes

Thank you for all the replies, and sorry I didn’t engage more in the discussion. This last table looks very nice indeed, and warnings should suffice in most cases.

1 Like

trying to reactivate this old thread as I think it would be beneficial to have the proposed change as suggested by julien. IMO good enough if only for scala 3.x
Are there reasons why this idea was abandoned?

5 Likes

I think the main reason is that nobody within the compiler team seems to be interested in implementing it. Other than that, I understand that adding a new keyword for such a specific thing might be too much…

Would you @robstoll be interested in implementing a PR in the dotty project?

Maybe just to add, I run into the problems of override all the time. I went from not using it for implementations to avoid accidental overriding to using it now because I want compiler errors when underlying API changes, but now I start accidentally overriding existing implementations. I still think the distinction between these two very different things would be worthwhile to support in Scala, no matter in what way.

4 Likes

I use override a lot and find it very helpful. Part of the purpose is to discover when I’m not overriding. When I started using Scala and in C# before that I no doubt used inheritance too much. But I’m just one of those people that has to learn from my own mistakes and riles at having to live with the mistakes of others.

I still use some complex inheritance hierarchies, but I’ve come to the view that non simple inheritance hierarchies can be very useful, but only where the hierarchy can at some point be fixed. Where there is a final natural correct form that models the entities in question, even if takes some time to arrive at that final solution.

But then I’m a bit of a heretic in that I not only think one can be too inheritance hierarchy orientated, but one can be too immutability orientated. Although I think its helpful to explore the extremes of different software development paradigms.

However i can’t see how an “implement” keyword would really help.

it helps when you have class Impl extends Interface with BaseImpl, because here you have zero indicator whether you accidentally override an existing implementation (and might need to call super.method). Whether the keyword or annotation is implement or some other word, these two things are really separate issues, and right now you cannot advise on any form as best style / practice because using override or not has both advantages and disadvantages.

3 Likes

as suggested by @julienrf, sounds reasonable to have both separated

  1. A keyword for adding a required method @implements
  2. A keyword for replacing an existing method @override

On the compiler side would expect:
Throw error when trying to implement an already implemented method
Throw error when trying to override a method not implemented

1 Like

Doesn’t sound too bad. I thought about it a bit longer and think it would make sense to set this into context of open which seems to me is not fully implemented. I’ll try to write up a PRE-SIP. Depending on what the outcome is there I come back to this thread :slight_smile:

4 Likes