Re: $this scoping (static methods) was: Bug 12622 Addressed in PHP 4.2.4?? Addressed in Zend 2.0??

From: Date: Sat, 14 Sep 2002 04:56:35 +0000
Subject: Re: $this scoping (static methods) was: Bug 12622 Addressed in PHP 4.2.4?? Addressed in Zend 2.0??
Groups: php.dev 
Request: Send a blank email to php-dev+get-88315@lists.php.net to get a copy of this message
I have no issues with supporting parent:: and self:: - those are fine. They need to work the way they do now. The ability to call down a class hierarchy is also useful. The bug reports are not complaining about calling the base class function from object A. If you have class A extends class B extends base_class A::foo(){base_class::foo();} is perfectly ok as is. This should and IS a class method call. base_class::foo(){A::bar();} needs to be forced to be a static method IF and ONLY IF base_class::foo() is being called from within an object of any type other than A. From an object of type A, the same function would call the A class method. This is the error I am reporting. I am not complaining about being able to call arbitrary points within the class hierarchy from within the most derived class, up and down, but rather on an object that is only partway down the hierarchy behaving like it was an instance of the most derived class. Is this making any better sense? I do not see a point to preventing class method calls just because there is no $this-> involved. That's not the issue. How can you call a class method from within an object which does not satisfy the IS- A relationship for the class in which the method resides. In the above case, an object of type A is also an object of type base_class. But an object of type base_class is not an object of type A. Inheritance is not reflexive. I haven't taken a look at the Zend engine yet, but at compile time, don't we know if an object contains a particular class method? Or do we only have the fully derived hierarchy? More comments? Alan Knowles (alan@akbkhome.com) wrote*: > >This pops up occasionally, Zeev/Andi should be able confirm that it's >not currently in ZE2. > >As far as remedies go... > >the reason that currently $this is passed on all static method calls is >to support parent:: and self::(ZE2), > >It has a few benefits- like making your code easier to read if you are >using a long tree of inheritance: eg. >where A extends b extends c extends d ... extends base_class { > base_class::somemethod(); // inside A would at least enable you to >work out what was being called. > >however, there are occasions where this is not desirable. (as a few bug >reports have noted.) > >Solutions >----------------------- >Suggested solution (for anybody wishing to implement it......) >would be to declare static functions explicitly, and when calling these >methods, no $this would be carried into the function scope. > >static function xxxxxx () { > >} > >Note: however there are alot of hidden implications to this, like >dealing with inherited static methods? dealing with static and non >static methods with the same name, extra compile time and exectute time >checks/lookups.., more complex behavior making it 'easier to' >accidentaly introduce user side bugs. > > >Implementations? >---------------------- >Option A) >This could be implemented similarly to the private protected stuff: eg. >name mangling on the function, >a static function would be stored in the hash table as \0xxxxxx > >changes: >Parser/compile time, >an extra flex rule for this. (which adds the \0 on) >(note: defining static function xxxx() and normal method xxxx() would be >valid! -however the non static method would always be called = otherwise >compile time checking would be required....) >Execute time: >when class::method() 's are called, first do a lookup on non-static >method, then lookup on \0 prepended method. > >Cons: dealing with multiple definitions of a single method in a class >would be slower at compile time (due to extra checks needed) >-------------------- >Option B) >An additional flag on the function defintion (type zend_bool), that >indicated if $this was to be passed on static methods. > >Cons: dealing with inheritance may prove odd/unexpected... >- parent method x() is static. >- inherited method x() is not... (programmers mistake for example)... >how complex would the resolution method for this have to be... - >compile time rules about not overriding static methods with non static >methods...... > >--------------------- > >I guess the more you look at it, implementing this has alot of pitfalls >- eg. moving from one 'not too bad' unexpected behavior ($this scoping), >to a highly complex compile time checking that may induce interpretor or >application errors accidentally..... > > >thoughts/comments anybody... > >Regards >Alan > > > > > > >Shamim Islam wrote: > >>I have discovered this problem recently with my own work with classes and objects >>in PHP. It appears that something that is incorrect does not fail when it should. >> >>The original bug is listed at http://bugs.php.net/bug.php?id=12622^&€¯sl >>¥o‚ñfR¸ÜÉ >> >>I discovered this in the process of posting my own bug report on this problem. >> >>PHP should catch these errors, IMHO as opposed to us spending time finding them. >> >>Also, is there anywhere in the documentation that correctly explains the semantics >>of when the $this context is passed to static method calls? >> >>I feel that to be in line with OO doctrines, any object should be able to call any >>method in its class hierarchy as if it were a class method call (including parent) >>(pass the $this) and any method not in its class hierarchy as a static method call >>(do not pass $this). >> >>This is illustrated below. >> >>Comments??? >> >>========================================================== >>The following fails, but for the wrong reason. >>========================================================== >> >><?php >>error_reporting(E_ALL); >>class A >>{ >> var $a; >> // Making a static call to class B - the only way it makes sense. >> function example(){echo $this->a;B::Example();} >>} >> >>class B extends A >>{ >> var $b; >> // This should fail when called from objects of type A. >> // but not because b as a property is missing but because >> // $this is undefined in this context. >> function example(){echo $this->b;} >>} >>$a=new A; >>$a->example(); >>?> >> >>================================================================== >>The following DOES NOT fail, but it should. Causes a silent error >>================================================================== >><?php >>error_reporting(E_ALL); >>// Example of bug in PHP class method passing $this incorrectly >> >>class test1 >>{ >> var $a; >> function test1() >> function showMe() >> { >> // Since test3::showMe was called as a static method >> // This too should be a static method call with no $this >> echo 'In test1::showMe<hr>'; >> echo 'Next 2 lines should fail since this method was not called from >>within this object<br>'; >> echo '$this is of type '. get_class($this)." in >>test3::showMe<br>\n"; >> echo "test1::showMe:a=".$this->a."<br>\n"; >> } >> // Class member to test static method call >> function callMe() >> { >> echo 'In test1::callMe<hr>'; >> echo '$this is of type '.get_class($this)."in >> test1::callMe<hr>\n"; >> echo 'Calling class method test3::showMe from an object of type >>test1<br>'; >> echo '$this should not be passed since test3::showMe does not exist >>in objects of type test1<hr>'; >> // This is a static method call, since test1 objects >> // do not have a test3::showMe. >> test3::showMe(); >> } >>} >> >>class test2 extends test1 >>{ >> function showMe() >> { >> echo 'In test2::showMe<br>'; >> echo "Next 2 lines should fail since objects of type test1 cannot >>pass \$this<hr>\n"; >> echo '$this is of type '. get_class($this)." in >>test2::showMe<br>\n"; >> echo "test2::showMe:a=".$this->a."<hr>\n"; >> echo 'Calling parent::showMe<hr>'; >> // Since test3::showMe was called as a static method >> // This too should be a static method call with no $this >> parent::showMe(); >> } >>} >> >>class test3 extends test2 >>{ >> function showMe() >> { >> echo 'In test3::showMe<br>'; >> echo "Next 2 lines should fail since objects of type test1 cannot >>pass \$this<hr>\n"; >> echo '$this is of type '. get_class($this)." in >>test3::showMe<br>\n"; >> echo "test3::showMe:a=".$this->a."<hr>\n"; >> echo 'Calling parent::showMe<hr>'; >> // Since test3::showMe was called as a static method >> // This too should be a static method call with no $this >> parent::showMe(); >> } >>} >> >>// object $a is of type test1 >>$a=new test1; >>$a->callMe(); >>?> >> >> >> >> > > > > >

« previous php.dev (#88315) next »