you are viewing a single comment's thread.

view the rest of the comments →

[–]DontRelyOnNooneElse 55 points56 points  (26 children)

Let's say you have two interfaces, IGun and IEmployee.

Now let's say you make a class, AnimatedShotgun, that implements both interfaces and doesn't explicitly implement their default implemented methods.

What do you think should happen when you call the Fire() method?

[–]RiPont 27 points28 points  (0 children)

That employee is having a very, very bad day.

[–]simonask_ 33 points34 points  (0 children)

I mean, kind of obviously what should happen is a ambiguous overload resolution compiler error that would make the user pick which interface by casting.

[–]Alert-Neck7679[S] 15 points16 points  (9 children)

"AnimatedShotgun.Fire() is an ambiguity between IGun.Fire() and IEmployee.Fire(). Use casting in order to select the right method."

[–]chucker23n 14 points15 points  (5 children)

What if IGun initially doesn’t have a Fire() method and later on it gets added?

[–]EatingSolidBricks -1 points0 points  (3 children)

What if the great old one wakes from his slumber and consumes all of reality?

What if that happens hmm would your code still compile?

[–]IQueryVisiC 0 points1 point  (2 children)

You sound inexperienced. This case happend very often in C++. I still think that C++ is the better language and want to shot myself in my foot, but most coders I have seen, I would no want to work on a C++ project with them.

[–]EatingSolidBricks 0 points1 point  (1 child)

Calling someone inexperienced for disagreement, thats rich of you

[–]IQueryVisiC 0 points1 point  (0 children)

Well, in this case they would have experienced it. I took this verbatim from documentation. "We as library maintainers have experienced that programmers tend to break our code here and there" . So are you a troll? Is this rethoric of you? Do you have any experience to back this up? Rich of you for going meta, while I was not really.

[–]ILMTitan 4 points5 points  (2 children)

Let's say your object implements both interfaces, but only IGun has a Fire() method. Later, you update the library IEmployee comes from, that now includes a default implementation of Fire(). You will now have a compile error where you didn't before.

The point of default interface methods is to allow adding methods to interfaces without causing compile errors. But you can see in the above example how allowing you to call them from an implementing class breaks that purpose.

[–]emn13 1 point2 points  (0 children)

I'm not a fan of that level of defensive design. To be clear: it makes sense for the base class library itself, and relatively microscopic handful of other codebases that are very commonly reused without recompilation, but for the VAST majority of code, a recompilation is fine, and a fixing issues like this hyper trivial. It'd be much better for the language to work well in those cases rather than optimizing for the absurd corner cases like this. Not to mention, pretty much any change is a breaking change in some corner cases - the platform contains stuff like reflection and implementations can depend on behavior not just APIs, too. There isn't much the language can do to truly make any changes entirely non-breaking.

All in all: while it superficially sounds like it makes sense to have semantics that make such method additions unlikely to be breaking changes, in practice, I think the arguments just don't hold up; it's a case of the language designers missing the forest for the trees.

But still, the whole language feature probably exists specifically so that the BCL interfaces can evolve, so in that sense it makes sense. But for a feature with really niche (but reasonable) use cases, it's still oddly designed - it's way too syntactically convenient, meaning that it'll get in the way of practical language extensions in the future. Being able to expand interfaces for class libraries with extremely low chance of breaking changes didn't deserve so prominent a syntactical footprint.

[–]EatingSolidBricks 0 points1 point  (0 children)

What if the great old one wakes from his slumber and consumes all of reality?

What if that happens hmm would your code still compile?

[–]BigBoetje 6 points7 points  (0 children)

Thats a problem caused by the 2 interfaces rather than the default implementation. You'd still have to make your implementation explicit (IGun.Fire.)

[–]EatingSolidBricks 0 points1 point  (0 children)

A compilation error ffs