On 26/05/2018 16:39, Pedro Magalhães wrote:
On Sat, May 26, 2018 at 3:04 PM, Rowan Collins <rowan.coll...@gmail.com <mailto:rowan.coll...@gmail.com>> wrote:

    Note that this example also works in Java:
    
https://tio.run/##vZMxb9swEIVn61fcKKctbWctMhUIuhgomqIdigwn8mIxpUiDPNkpDP92hxJlW4rsIUBRQhP5@O670@MzbvDTs/pzOGAR2KNkkAZDgG9eS4JdBnGtvWOSTAqUqwtDsEFT0@f2LAnirpbpTt7XTDuHZnGpg2h34a7vsD/7nBhGFVfE33H7s7mVT8eVz6p75yvkeLPT9gBmM/iCxgTAnn9FXDoF7gm2pZYlbciDLLVR3Rx0aMFPJp649haWyKXwrrYqb/sa8E1HjXWYG6cVoFJ5mq7jkvy/IGyNLg36w106Exfmt8/2WZYsfuDLvSdKVPTCZNWbBCT@ge7qjw71mnyeto@lLudoQNVz6IZ8bmRE3CL80lxGpCHxbpTIo@x/AsMNLMRtDzvriBL@ErWN1yfdZmDkYzyqeJQ/sNd29fsR0K9CU2gySUPH@HYsbQd/Il/MxTyCHzVFp@k3f9Y8/A1MlXA1i3UswsbmKC48nGvi4qo4fjHAX8nTR0AL2sa2bBPzp2FwttoYQCkpvA16VcRsR3mfPLqiaN5M8W78ZvCHwys
    
<https://tio.run/#%23vZMxb9swEIVn61fcKKctbWctMhUIuhgomqIdigwn8mIxpUiDPNkpDP92hxJlW4rsIUBRQhP5@O670@MzbvDTs/pzOGAR2KNkkAZDgG9eS4JdBnGtvWOSTAqUqwtDsEFT0@f2LAnirpbpTt7XTDuHZnGpg2h34a7vsD/7nBhGFVfE33H7s7mVT8eVz6p75yvkeLPT9gBmM/iCxgTAnn9FXDoF7gm2pZYlbciDLLVR3Rx0aMFPJp649haWyKXwrrYqb/sa8E1HjXWYG6cVoFJ5mq7jkvy/IGyNLg36w106Exfmt8/2WZYsfuDLvSdKVPTCZNWbBCT@ge7qjw71mnyeto@lLudoQNVz6IZ8bmRE3CL80lxGpCHxbpTIo@x/AsMNLMRtDzvriBL@ErWN1yfdZmDkYzyqeJQ/sNd29fsR0K9CU2gySUPH@HYsbQd/Il/MxTyCHzVFp@k3f9Y8/A1MlXA1i3UswsbmKC48nGvi4qo4fjHAX8nTR0AL2sa2bBPzp2FwttoYQCkpvA16VcRsR3mfPLqiaN5M8W78ZvCHwys>


Java's behavior stems from the fact that protected offers package-level visibility. A concept that we don't have in PHP. To offer a counter example, C# disallows it: https://ideone.com/DkiCeM

I stand corrected on the Java front; I had incorrectly assumed "protected" had the same meaning there. The error message given in that C# example is interesting:

> Cannot access protected member `foo._protected' via a qualifier of type `foo'. The qualifier must be of type `kid' or derived from it

The compiler is able to complain in advance that the access would not be type-safe. You can actually substitute "foo b = new kid();" and get the same error, because it's the static type of the variable that is the problem, not the dynamic type of the instance. PHP could never detect this at compile-time, and doesn't guarantee the safety of *any* method call, so it would have to fail at run-time.


PHP started allowing this in 5.2 due to a bug report stating that it should be possible: https://bugs.php.net/bug.php?id=37212

As I look at more examples of this, I am finding there are inconsistencies across two dimensions: methods vs properties, and inheriting the member directly vs overriding it. See https://3v4l.org/NSCKW and https://3v4l.org/otbY1 for various versions.

In PHP 5.1, a protected *method* could be called on any instance with a shared parent, as long as it was declared on the parent class, and wasn't re-declared in the sub-class. This is weird, because it's a reasonable assumption that if you can call a method on an instance of A, you ought to be able to call it on any sub-class of A. With this original behaviour, a sub-class can break that assumption simply by declaring an over-ride to a protected method.

In PHP 5.2, this inconsistency was removed, and the sub-class can call a protected method of its parent even if given a sub-class that over-rides that method.

Properties, meanwhile, are a step behind: in PHP 5.1, a protected property couldn't be accessed on an instance with a shared parent at all, but since 5.2, it's had the inconsistent access previously enjoyed by methods: you can access it as long as it hasn't been re-declared in the child class. Again, this inconsistency doesn't make much sense, and breaks substitutability.


From the error message, the C# solution appears to be to ban access not just on parallel sub-classes, but on instances of the parent class itself. Translated to the run-time typing of PHP, this would also need to throw an error:

class A {
    protected $x = 1;
}
class B extends A {
    public function foo($a) {
        echo $a->x;
    }
}
$a = new A;
$b = new B;
$b->foo($a);


That would at least be a consistent alternative to the current behaviour, although I'm not entirely sure if there are any concrete benefits of changing. Both behaviours are quite hard to explain, and may be surprising to some users.

Regards,

--
Rowan Collins
[IMSoP]

Reply via email to