If you voted against the Interface Default Methods RFC for #PHP, please take a moment to read some of the most recent mailing list replies, starting with @Crell’s here: https://externals.io/message/120725#120798

I agree this feature goes against a lot of what I’ve learned as “best practices,” but I did a lot of introspection on this and decided that this feature is good for the future of the PHP language. It unlocks a lot of potential.

[RFC] [Discussion] OPcache Static Cache - Externals

#externals - Opening PHP's #internals to the outside

It looks like at least one person flipped their vote, so the vote is an even 50/50, now. It needs a 2/3 majority to pass, so if 5 more folks flip their votes, it’ll be passing.

@ramsey I changed my vote to yes.
What changed my mind was something @Crell said:
"Traits are a surgical tool with a narrow set of uses, and systems that over-use them cause problems."

The same can be said for default methods. Like traits, there are some specific use cases for them, but if you are using them too much, you are doing something wrong.

There is one thing I still disagree with the RFC. Using default methods to avoid a BC break when adding methods to an interface is a terrible idea.

@mauriciofauth @ramsey @Crell The problem is that BC break is still there. Speaking semver, if you a method to an interface, even if you provide a default, you *still* need to release a new major. So the only theoric good use of default methods, that is prevent BC breaks, is not achieved, thus this RFC does nothing good and a lot of harm. Just to name one thing, the implications with intersection types is huge.
@gmazzap @mauriciofauth @ramsey What does it have to do with intersection types?
@Crell @mauriciofauth @ramsey I have a function that accepts an intersection of a class of mine + a framework interface. The framework adds a default method to that interface, and that method exists in my class with a different signature. The intersection type is now invalid. So the framework break my code, even if my code did not change.
It means this RFC which aims at solving BC breaks introduces new way of creating breaking changes.
@gmazzap @mauriciofauth @ramsey That's no different than if the interface added a method with a different signature than yours and didn't provide a default. That's still going to break in subtle and annoying ways.
@Crell @mauriciofauth @ramsey Exactly. What you are saying is: the problem we want to solve is prevent BC breaks with interfaces. This RFC does not solve the problem, but we want it anyway.

@gmazzap @mauriciofauth @ramsey No, the RFC adds certain functionality, and improves BC in one way, but not in this other way that's more or less the same either way.

It's not perfect, but still a net win.

@Crell @mauriciofauth @ramsey when I criticized this RFC people answered me that it would be a way to overcome BC breaks, so that is where I'm coming from. Now it seems the selling point is "the correct way" to implement multi-inheritance. Can I ask why is it better than implementing multi inheritance explicitly? As in allow `extend` to be followed by multiple classes? Isn't that the same feature but less impactful, more explicit, and more "natural" for PHP?

@gmazzap @mauriciofauth @ramsey From a completely abstract place:

class A extends B, C {}

and

class A implements B, C {}

would be effectively equivalent in power. The difference is squishy feel stuff.

Classes "are supposed to" have impl, interfaces "are supposed to" have type defs. If done via interfaces, no default method becomes the mental default.

Honestly, for me the strongest arg is "via interfaces is more common," so it's easier for ppl coming to the language.

@gmazzap @mauriciofauth @ramsey At some point in this, effectively, interfaces and abstract classes merge into one concept. What particular syntax that uses is subjective.

I couldn't say why the market has gone with interface-based syntax in most cases without a lot more research, but that seems to be what's happened.

@Crell @gmazzap @mauriciofauth @ramsey

I would take a shot at guessing it’s the mental model. Defining an abstract class is about thinking of an object behavior with multiple levels of inheritance and where that object fit in the hierarchy. Defining interfaces is just about an expected contract where multiple levels of hierarchy are barely relevant. I guess there’s nothing really technical about it, just how the idea embedded in people’s minds.

@deleugpn If we stop talking about syntax differences, and focus on concepts, we find out many languages have a construct that is
both abstraction and partial implementation. And guess what, PHP has it as well, it's abstract class. But other languages allow multiple inheritance from that construct, PHP doesn't. Support multiple names after `extend` and PHP becomes inline with other langs.

@Crell @mauriciofauth @ramsey

@deleugpn It's true that many other langs do not have an abstraction-only construct, like PHP interfaces, but if you add implementation to interfaces, you make abstract classes redundant. And because I doubt you'll ever be able to deprecate abstract classes, than I think we should avoid create a duplicate feature in the language. Especially when we can obtain the same thing other language have by allowing multiple inheritance on abstract classes.

@Crell @mauriciofauth @ramsey

@gmazzap @deleugpn @mauriciofauth @ramsey

Java, Kotlin, and C# all have abstract classes, and interface default methods. Only Swift does not.

I agree it seems redundant, but other languages seem to still keep both.

Also, multiple-inheritance via extends would make interfaces redundant just as much. The conclusion I draw is that the line between the two is much more murky than the Java 2 mindset (still prevalent in PHP) would have us believe.

@Crell @gmazzap @deleugpn @ramsey
Why we can't have multiple inheritance via extends and interface default methods?
@mauriciofauth @gmazzap @deleugpn @ramsey I'm sure it's technically feasible, but for anyone who thinks even just one of them would be confusing, that would be multiplicatively more confusing. 🙂

@mauriciofauth

So same feature, implemented in two different ways?

@Crell @deleugpn @ramsey

@gmazzap that’s what most languages designed in the 90’a seem to have. There’s already stigma around multi inheritance and it has the potential to create a messy structural hierarchy, which is the primary reason I don’t care much for it. The discussion seems to have lodged itself in a technicality that more or less revolves around “hey look this is mutiple inheritance” when the fact is we barely care for it.

@mauriciofauth @Crell @ramsey

@gmazzap what we want is potential reduction of BC breaks when modifying a contract and also the ability to provide implementation for contracts that barely need to deviate from a single implementation. Whether folks will use it to make multiple inheritance is like arguing that if conditions are bad because it allows too much flexibility to make the codebase a mess. You can’t have a modern language without “if”

@mauriciofauth @Crell @ramsey

@deleugpn
The potential resolution is a problem for me as well.
As others have said, this introduces the risk of people releasing changes to interfaces withot calling for the BC break because they have added default methods.
Also, if you are one of the few people affected by the BC break, telling that will be hard, unless you have 100% coverage.

@mauriciofauth @Crell @ramsey

@gmazzap

I guess maybe we can agree here that this is a dead and pointless discussion and neither of us will change our minds

@mauriciofauth @Crell @ramsey

@deleugpn

I'm telling to build multi inheritance via abstract class, so no stigma from me.

But the thing is this that even if you don't care, that is a fundamental change in the language, and should not happen by accident, IMO.

@mauriciofauth @Crell @ramsey