Hey,

On 17.3.2025 19:58:39, Rob Landers wrote:
On Mon, Mar 17, 2025, at 19:05, Bob Weinand wrote:
. The idea that extending the parent class doesnt no inherit the child classes doesnt make sense to me. As then if you extend a parent class and call a function of that class which could rely on the existence of an inner class, I can see a lot of headaches caused by this exact scenario. As a developer, if I extend a class, I expect the entire dependance of that class to be inherited, otherwise the extending class won't work.

I'm not sure what you mean. When you inherit a class, you do not necessarily inherit everything from its superclass. You are free to override it however you want. Since we are defining "types" in the sense of PHP, we cannot merely inherit a "type", otherwise we would cause all kinds of issues with LSP. This is specifically why inheritance works the way it does in this RFC and why `static::` is forbidden.

I don't understand the problem here.

for each nested class in parent class:
    class_alias(substitute parent class with child class in class name, class name)

Very simple. There's no magic needed, it can be simply class aliases. This will also make static, self and parent trivially work.


PHP doesn't go out of its way to prevent the developer from violating LSP -- but where it can, it does. If a type were inherited, then the subclasses wouldn't be able to guarantee that an inner/nested class implemented the parent inner/nested class. Or, if it did, it would require that all subclasses using a class of the same name MUST inherit from the parent class as well.

This is non-trivial to implement as the parent class may or may not have been compiled yet when we are compiling the subclass. So, we have no idea what the parent class actually looks like until runtime. Further, it is much simpler to reason about each class as a distinct type vs. maybe inheriting a type from a supertype.

Thus, if you want to inherit from the super-class's inner classes, you can, but this RFC won't force you to do so. In my mind, this is the biggest argument for a `\`, because the enclosing class acts more like a namespace than a type, from the perspective of the inner class.

If we were to embrace `\`, then it could be argued that a namespace is technically a class in itself, (but a partial class, to borrow from C# terminology) and every class in a namespace is essentially just a public class in that super-class/namespace.

Nobody has argued that perspective, but I believe it may be interesting (and would lay a foundation for namespace private/public class behavior/visibility). That being said, it truly does cause issues with autoloading -- at least, PSR-4 autoloading -- and I'm not sure whether we should solve that problem here; however, it is something to be cognizant of, for sure. There are other types of autoloading supported by tools, such as composer, that do not have any issues with using `\` as a separator.

Okay, I see the point with LSP. I'm not sure whether we need to preserve LSP for that specific scenario, but neither can I say that we should ignore it.

(Effectively implementing LSP would mean that there's an implicit interface matching all public method signatures of the parent class, for child classes - which is doable, but possibly too much for the initial RFC.)

I would however ask, should we not implement LSP compatible inner classes, to enforce that no child class may name a class the same than any non-private inner class declared by any of its parents, until we resolve this question (in possibly a future version of PHP).
I do not think we should bar ourselves from allowing this in the future.

However nice grand unified naming schemes may seem, I don't think it's a good idea to pursue. Clarity and explicitness shall reign supreme here. I also don't think that the proposed visibilities are applicable to namespaced classes. In particular and in practice shared internal classes are not necessarily directly organized in a way it makes sense to organize inner classes. Also visibilities like protected propagate along the inheritance chain, something which is not given with (outer) namespaced classes.
The less we mix these slightly different concepts, the better.

"It's similar, except in these and those cases" is the death of all consistent experiences. Thus, let's not even attempt to pretend it is.
And not pretending starts with using a different symbol than a backslash.


Bob

Reply via email to