Bug #50892 [Com]: Protected members of non-congruent children classes are visible

From: Date: Sat, 26 May 2018 16:49:18 +0000
Subject: Bug #50892 [Com]: Protected members of non-congruent children classes are visible
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-215385@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=50892&edit=1 ID: 50892 Comment by: rowan dot collins at gmail dot com Reported by: EdwardDrapkin at gmail dot com Summary: Protected members of non-congruent children classes are visible Status: Open Type: Bug Package: Class/Object related Operating System: Irrelevant PHP Version: 5.3.1 Block user comment: N Private report: N New Comment: @giovanni: Why would the expected behaviour there be to print 10? Re-declaring a property doesn't create a second property with the same name, it changes it polymorphically just like re-declaring a method does. Either the method can see the value 10, or it cannot see any value. class C { protected $x = 10; public function m() { print "x=" . $this->x . "\n"; } } class D extends C { protected $x = 20; } $d = new D(); $d->m(); // "x=20" Previous Comments: ------------------------------------------------------------------------ [2018-05-26 16:42:19] rowan dot collins at gmail dot com > https://3v4l.org/TM6jk This appears to be exactly the opposite complaint from the original: in this case, the protected property *can't* be accessed in a different child. So we certainly have an inconsistency here - between methods and properties, and based on whether the member is inherited directly or over-ridden / re-declared. The case of a re-declared property is currently the only one that errors, so the simplest change would be to remove that error. Class C knows that the access is legal when given an A, so assumes it's valid for all sub-classes of A; sub-class B2 is currently able to break this assumption for a property, but not for a method. ------------------------------------------------------------------------ [2018-05-26 15:21:19] giovanni at giacobbi dot net I agree with arth dot inbox at gmail dot com, the original bug report is wrong but this actually should be filed as a new bug imho: Reproduce code: --------------- class C { protected $x = 10; } class D extends C { public function m(C $c) { print "x=" . $c->x . "\n"; } } class E extends C { protected $x = 20; } $d = new D(); $e = new E(); $d->m($d); $d->m($e); Expected result: ---------------- x=10 x=10 /* note 10, NOT 20! */ Actual result: -------------- x=10 PHP Fatal error: Uncaught Error: Cannot access protected property E::$x in Standard input code:9 Stack trace: #0 Standard input code(21): D->m(Object(E)) #1 {main} thrown in Standard input code on line 9 ------------------------------------------------------------------------ [2018-05-26 14:31:24] arth dot inbox at gmail dot com We should not to stand on other language behavior. One more time: https://3v4l.org/TM6jk For now it just breaks SOLID. ------------------------------------------------------------------------ [2018-05-26 14:25:45] rowan dot collins at gmail dot com Sorry, slight mistake in my example: to be equivalent to this report, the Subclass::add(ParentClass $other) method should be declared on one of the child classes. But it still works in both languages: https://3v4l.org/IInDq https://tio.run/##vVPBThsxED1vvmKOm5Ya6LXihIS4IFWA2kPVw6w9ZA1eO7JnEyrEt6fe9YbYJDkgVbX2NH5@8@bN20dc4ZdH9bTZYBPYo2SQBkOA715LgpcZxLP0jkkyKVCubwzBCk1P38a7BIhVLdObOsfMJ4bhcKuDGKtwkTO87njeNOx1XBDf4vrH8Kqe73feoa6c75DjywmbCTg9hUs0JgBm/B1x6xS4B1i3Wra0Ig@y1UZNPugwCn8j8cS9t3CD3Arveqvqca5C33w72Otsllju8fnKEyVT6ZnJqncWpzkK3FEnQ78kX6fyttXhRRWyMoZpit1KSpokZuW0AlSqTnIct@T/hZ8j0aFYfL5Id@LAtjMzRzk/NbfRrdLMl700bmH/00v4BOfiayZ7NilK8m9Q2/i8moqBkbdmd/GqvmOv7eLXb0C/CEOjqipigfH3sbQuslKfn4mzqL@qiqmbCZoXd9C7P4GpE65nsYwt2dgaxYFf6Bi4OQqOXwzHNXk6AbSgbRzSDhF6KBO@1sYASknhfYi6JuYmwnPlkRXFkMfmw/KHNWw2fwE ------------------------------------------------------------------------ [2018-05-26 14:11:34] rowan dot collins at gmail dot com This may seem odd, but is actually perfectly reasonable if you consider polymorphism: - Access is class-based, not instance-based: you can call private members of a different instance of the same class. - For the same reason, you can access protected members on an instance of a parent class. - If you ask for an instance of class A, you may at run-time actually receive an instance of some sub-class of A. - So, if classes B1 and B2 both inherit from A, a method on class B1 might ask for an instance of A, and be given an instance of B2; when it calls a method on that instance, it's the definition in B2 which will be accessed. Here's a concrete example: https://3v4l.org/LeClo 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 The example from the original report also works in Java: https://tio.run/##fY9BDoMgEEXXcgriShflAqZH6Mpl0zSg1CAKDYy2TePZKQTUpovuZv7/mf@mpzM99K10rhmotfimNX6j7D6xQTS4BiNUh69pPeKc5lXmbaOBN8DbPbEpPrQteYUWhOJlRg3mT@Cq3Vp2U4r210yds/YWcAtFGdQsuMyXKP4IJ4uy8mL9ssBHoicgd88DgyoYSdT/AitnyCyBJpVGqBMV6ovEAoUVaPRWEX8/XzA1nY104Q@Z6Pwc6SSJ/KnEuQ8 I'm of the opinion that this is not a bug. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=50892 -- Edit this bug report at https://bugs.php.net/bug.php?id=50892&edit=1

« previous php.bugs (#215385) next »