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

Reply via email to