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]