Re: Protected inheritance hierarchies
| From: | Rob Landers | Date: | Sat, 02 Aug 2025 19:12:59 +0000 |
| Subject: | Re: Protected inheritance hierarchies | ||
| References: | 1 2 3 4 5 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-128374@lists.php.net to get a copy of this message | ||
On Sat, Aug 2, 2025, at 19:04, Alexandru Pătrănescu wrote:
>
>
> On Sat, Aug 2, 2025, 17:10 Rob Landers <rob@bottled.codes> wrote:
>> __
>>
>>
>> On Sat, Aug 2, 2025, at 16:04, Alexandru Pătrănescu wrote:
>>>
>>>
>>> On Sat, Aug 2, 2025 at 12:10 PM Rob Landers <rob@bottled.codes> wrote:
>>>> __
>>>> On Tue, Jul 29, 2025, at 20:11, Jonathan Vollebregt wrote:
>>>>> I came across this edge case today:
>>>>>
>>>>> https://3v4l.org/R3Q8D
>>>>>
>>>>> Both psalm and phpstan think this code is A-OK (Once you add the
>>>>> requisite type hints) but it causes fatal errors way back to PHP 5..0.0
>>>>>
>>>>> ...<snip>...
>>>>
>>>> It's not an edge case, in C2, you redefine a protected variable with the same
>>>> name and shadowed the original $v. That $v is different than C's $v. It's easiest to see
>>>> this with static access: https://3v4l.org/0SRWb#v8.4.10
>>>>
>>>> However, I don't know of any way to unshadow a property from $this to access
>>>> the ancestor's value (other than using private access), but it exists and takes up memory; just
>>>> accessing it is the hard part.
>>>>
>>>> — Rob
>>>
>>>
>>> Hi Rob,
>>>
>>> I'm pretty sure that there is no shadowing happening in the example.
>>> When the child instance is created, there is just one slot for the property, as the
>>> child one replaces the parent one.
>>> So basically the child property overrides the parent property rather than shadowing it.
>>>
>>> True shadowing (two slots) only occurs when the parent property is declared private.
>>>
>>> It's just that when redefining, it stores the declaring class, and so there is
>>> this sibling class access issue.
>>>
>>> I'm wondering now if the access shouldn't be relaxed, in case we have the
>>> parent class that initially defined the property.
>>>
>>> Of course, we should focus on non-static properties, as static ones are different
>>> things, and there is some shadowing there.
>>>
>>> --
>>> Alex
>>
>> Hi Alex,
>>
>> I’m not sure what you mean?
>> https://3v4l.org/WKILh#v8.4.10
>>
>> There is clearly shadowing going on.
>>
>>
>
> Hi Rob,
>
> As I said, let's leave aside the static case, as the question from Jonathan was not about
> that.
>
> Given the class P that defines a protected property with value 1,
> and a class C that extends P and re-defines the protected property with the value 2,
> please show me an example where you could get from an instance of class C the value 1 of the
> parent class property that you think it's shadowed.
> Bonus point, if you manage that, you could also set it to something else, and so have a hidden
> storage for any object of class C that is not really visible normally.
>
> As far as I know, there is no way to achieve that, and the reason is because at runtime the
> objects have a single slot for the protected property; the child class property overrides the parent
> class property when redeclared, and does not shadow it.
> But please prove me wrong.
>
>
> Thanks,
> Alex
>
I mentioned in my first reply, there is no way to get an instance-level property unshadowed. It is
there though (according to inheritance.c, if I’m reading it right, it is still accessible, just
not from user-land).
In any case, there are lots of interesting footguns with properties and inheritance: Problem with
abstract nested object · Issue #47 · Crell/Serde <https://github.com/Crell/Serde/issues/47#issuecomment-1890966829>.
> Could it be considered a bug that my first example produces a fatal
> error instead of trying to access the shadowed parent property that it
> has access to and is typed to use?
Other languages (such as C#, Java, etc: https://www.programiz.com/online-compiler/0ud6UO24mHOTU)
don’t allow you to access protected properties/methods on sibling classes. This is because
"protected" is usually used in the context of inheritance; access is usually restricted to
"myself" or "children" and a sibling is neither of those. If there is a bug, the
bug is that you can access a sibling’s protected properties, at all.
— Rob