Re: Re: Re: Ambiguity in the oop5 visibility docs

From: Date: Thu, 28 Mar 2019 10:14:47 +0000
Subject: Re: Re: Re: Ambiguity in the oop5 visibility docs
References: 1 2 3 4  Groups: php.doc 
Request: Send a blank email to phpdoc+get-969387197@lists.php.net to get a copy of this message
On 28.03.2019 at 10:32, Nikita Popov wrote: > On Tue, May 29, 2018 at 1:41 PM Rowan Collins <rowan.collins@gmail.com> > wrote: > >> On 27 May 2018 at 19:02, Andrew Gromov <andrewgrom@rambler.ru> wrote: >> >>> class A { >>> public function foo(){ >>> echo $this->b; // No property $b in parent class >>> } >>> } >>> >>> class B extends A { >>> protected $b = 'foo'; >>> } >>> >>> $a = new B(); >>> $a->foo(); // prints 'foo' >>> >>> In classic OOP, parent class can't access unknown to him member of child >>> class. >>> >> >> >> In PHP, classes don't really "know" anything about their structure - >> everything is looked up dynamically at run-time. At run-time, there is a >> property called "b" on the instance, and it is visible in the current >> scope, so the access is allowed. >> >> You mention "classic OOP", but I'm not aware of any formal definition we >> could reference here, only precedent from other languages. Most languages >> don't need to worry about this case, because the reference to $this->b >> would fail to compile unless b was declared; but PHP can't raise that >> error, because accessing a completely undeclared property is allowed. >> >> >> >> >>> And phrases like >>> >>>> can be accessed within the class itself and parent classes. >>> >>> explode the brain! How it can be - reverse inheritance, from child to parent!? >>> >>> >> I discussed a common use case for this in my first response on this >> thread: >> https://marc.info/?l=phpdoc&m=152727049709620&w=2 >> >> There is no *inheritance* from child to parent, just access from code >> written in a parent class to polymorphic behaviour in the child class. >> > > Want to bump this discussion again, because I still think that the current > behavior is incorrect. I think there are two different cases that got > conflated here: > > // This should work. > class A { > protected function foo() {} > } > class B extends A { > protected function test() { $this->foo(); } > } > class C extends B { > protected function foo() {} > } > (new C)->test(); > > This code should of course work. It should work because we have an A::foo() > method (the "prototype"), which happens to be overridden by C::foo(), but > that's not actually relevant. The inheritance check here is whether B has > access to the prototype A::foo(), which is has. If you consider that > inheritance is checked against the prototype, then there is actual "reverse > visibility" going on here. > > The other case, and the case that I believe should not work, is the > following: > > // This shouldn't work, but does. > class A { > protected function test() { $this->foo(); } > } > class B extends A { > protected function foo() {} > } > (new B)->test(); > > Here B::foo() does not have a prototype higher up in the hierarchy. We're > calling B::foo() from A, which should by any reasonable interpretation not > be possible. To allow this call, it should be necessary to also add a > protected function foo() to class A, possibly as an abstract method: > > // This should work. > abstract class A { > protected abstract function foo(); > protected function test() { $this->foo(); } > } > class B extends A { > protected function foo() {} > } > (new B)->test(); > > Here once again B::foo() overrides the prototype A::foo(), and A::foo() is > of course visible from A. > > I believe that the current behavior is a leftover from before the > introduction of the prototype mechanism in PHP 5.2. Previously just > checking visibility in both directions was a poor mans approximation of the > correct behavior. However, it both disallowed some legal cases (involving > non-linear hierarchies) and allowed illegal cases (accessing protect method > from a child). > > Since PHP 5.2 all the legal cases should be covered by the prototype > mechanism and the bidirectional visibility check is just a legacy leftover. > We should consider removing it for PHP 8. Changing the actual behavior should better be discussed on internals@, though. :) -- Christoph M. Becker

« previous php.doc (#969387197) next »