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