On Tue, Mar 18, 2025, at 03:37, Bob Weinand wrote: > 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. >
I'm not sure I understand what you are asking. But I think you are saying the following should be illegal? class ParentOuter { class ParentInner {} } class ChildOuter extends ParentOuter { class ParentInner {} // not allowed } > > 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. > This is true. > > And not pretending starts with using a different symbol than a backslash. > I have been thinking about this for a couple of days now... When thinking through the ramifications of my decision to use :> over ::, this will also affect generics, most likely -- whenever that happens. This is because if this RFC passes, generics will want to be consistent with whatever exists currently. If we were to use :>, then generics would probably look something like this to be consistent: class Box<T> { public function add(self:>T $item) {} } The same thing would also probably apply to :: class Box<T> { public function add(self::T $item) {} } With `\`, it nearly follows exactly what you would expect-ish: use \Box\T as T; class Box<T> { public function add(T $item) {} // or without use public function add(Box\T $item) {} } With `\`, we can also just automatically check the current class as part of namespace resolution when compiling: class Box<T> { public function add(T $item) {} } This would also make it easier to user inner classes: class Outer { public class Inner {} public function foo(Inner $bar) {} } The other syntax options do not allow this; at least, I don't think so. I'm very heavily leaning towards `\` as the separator. — Rob