#19376 [Bgs->Opn]: Class inheritance problem
| From: | shamim at poetryunlimited dot com | Date: | Fri, 13 Sep 2002 04:33:07 +0000 |
| Subject: | #19376 [Bgs->Opn]: Class inheritance problem | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-19287@lists.php.net to get a copy of this message | ||
ID: 19376
User updated by: shamim@poetryunlimited.com
Reported By: shamim@poetryunlimited.com
-Status: Bogus
+Status: Open
Bug Type: Scripting Engine problem
Operating System: Linux/Windows NT 4
PHP Version: 4.2.2
New Comment:
Please see bug report http://bugs.php.net/bug.php?id=19384 for further
details.
You say that static method calls take $this with them? But how can they
take them OUT OF the current class? Which $this is in effect in the
class of the static method?? What happens if the static method call has
it's own variable of the same name or function?
I did not see anywhere in the documentation that states that static
method calls take $this with them, even out of the current class.
I'm confused. How can an object of type A call a static method of class
B and have $this taken with it???
This violates class scoping as far as I understand it.
I don't see how this would enable multiple inheritance, especially
since PHP is supposed to be single inheritance anyway.
You're saying this isn't a bug? Isn't that like someone telling me a
year ago that &new was necessary and it wouldn't be fixed because it
was a feature, and now Zend 2.0 will do it by default???
Suggestions? Where should I take this issue? And where do I find the
documentation that clearly describes the expected behavior.
Thanks.
Previous Comments:
------------------------------------------------------------------------
[2002-09-12 23:25:15] alan_k@php.net
apologies for the brush of effect.
if you could mark the first instance where you think the behaviour is
unexpected it would help. I assume you realize that all static method
calls take with them the '$this' value of the calling objects (always).
It's a feature, and It has a few usefull side effects, like making a
sudo multiple inheritance possible...
------------------------------------------------------------------------
[2002-09-12 23:11:42] shamim@poetryunlimited.com
Thank you for explaining to me that I did not explain my problem
clearly.
My question was rhetorical. Having been a systems engineer for the past
15 years, I know that this is an error. I was merely trying to be
polite and draw your attention to it.
I do not appreciate the unwarranted brush off, nor do I appreciate
being told that this was a support request - I don't want to know how
to do something. I want something fixed. Thanks.
Hopefully you can correct this or alert Zeev that there is a problem in
calling static methods from within a class instance when that static
method contains the original class as part of its hierarchy.
It allows the $this context to be passed from an object to a static
method and back, violating class scoping. Please see the other bug
report for a more clearer example.
Shamim Islam
BA BSc
P.S. I will be posting this as many places as I can find a forum until
someone understands that class scoping is being violated willy nilly.
------------------------------------------------------------------------
[2002-09-12 18:15:37] alan_k@php.net
Sorry, but the bug system is not the appropriate forum for asking
support questions. Your problem does not imply a bug in PHP itself.
For a list of more appropriate places to ask for help using PHP,
please visit http://www.php.net/support.php
Thank you for your interest in PHP.
I cant see any unexpected behaviour here, - however it would help
*alot* if you made a shorter example...
------------------------------------------------------------------------
[2002-09-12 13:07:33] shamim@poetryunlimited.com
when an object of type test3 calls test3::showMe is the only time this
chain should function as displayed, I believe.
Thanks.
------------------------------------------------------------------------
[2002-09-12 13:05:53] shamim@poetryunlimited.com
Should I be able to do the following?
In the example below, class test1 is a base class for test2 which is a
base class for test3.
In an object of type test1, if I call the class method test3::showMe, I
would expect the class method test3::showMe would be called. This class
method (not member function) would would have no class context ($this),
since objects of type test1 do not have a member function
test3::showMe.
This call should therefore fail at the debug call.
Instead, the call traverses up to test3, and the recursive
parent::showMe calls reverse the traversal back to the class test1,
even though class test1 has no knowledge of class test3 or class test2.
Or so it should be. And for some reason the $this variable exists at
every level. Even though objects of type test1 do not have any test3 or
test2 object contexts.
I think the polymorphism is broken. Thanks.
Code follows.
===========================================================
<?php
Header("Content-Control: no-cache");
Header("Pragma: no-cache");
function debug(&$obj,$msg)
{
echo "$msg<br><pre>";var_dump($obj);echo
"</pre><hr>\n";
}
class test1
{
var $a;
function test1() {$this->a=0;debug($this,"test1->new");}
function setA() {$this->a+=1;debug($this,"test1->setA");}
function display() {debug($this,"test1->display");echo
$this->a."<br>\n";}
function callMe()
{debug($this,"test1->callMe");test3::showMe();}
function showMe()
{debug($this,"test1->showMe");$this->display();}
}
class test2 extends test1
{
function test2()
{debug($this,"test2->new");$p=get_parent_class($this);parent::$p();}
function display()
{debug($this,"test2->display");parent::display();}
function showMe()
{debug($this,"test2->showMe");parent::showMe();}
}
class test3 extends test2
{
function test3()
{debug($this,"test3->new");$p=get_parent_class($this);parent::$p();}
function display()
{debug($this,"test3->display");parent::display();}
function showMe()
{debug($this,"test3->showMe");parent::showMe();}
}
$b=new test2();
$b->setA();
$c=new test1();
$c->setA();
$a=new test1();
$a->showMe();
$a->callMe();
$a->setA();
$a->showMe();
$a->callMe();
$a->setA();
$a->showMe();
$a->callMe();
$a=new test2;
$a->showMe();
$a->callMe();
$a->setA();
$a->showMe();
$a->callMe();
$a->setA();
$a->showMe();
$a->callMe();
/*
Results:
test2->new
object(test2)(1) {
["a"]=>
NULL
}
--------------------------------------------------------------------------------
test1->new
object(test2)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test1->setA
object(test2)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test1->new
object(test1)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test1->setA
object(test1)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test1->new
object(test1)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test1->showMe
object(test1)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test1->display
object(test1)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
0
test1->callMe
object(test1)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test3->showMe
object(test1)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test2->showMe
object(test1)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test1->showMe
object(test1)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test1->display
object(test1)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
0
test1->setA
object(test1)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test1->showMe
object(test1)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test1->display
object(test1)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
1
test1->callMe
object(test1)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test3->showMe
object(test1)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test2->showMe
object(test1)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test1->showMe
object(test1)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test1->display
object(test1)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
1
test1->setA
object(test1)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
test1->showMe
object(test1)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
test1->display
object(test1)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
2
test1->callMe
object(test1)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
test3->showMe
object(test1)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
test2->showMe
object(test1)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
test1->showMe
object(test1)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
test1->display
object(test1)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
2
test2->new
object(test2)(1) {
["a"]=>
NULL
}
--------------------------------------------------------------------------------
test1->new
object(test2)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test2->showMe
object(test2)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test1->showMe
object(test2)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test2->display
object(test2)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test1->display
object(test2)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
0
test1->callMe
object(test2)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test3->showMe
object(test2)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test2->showMe
object(test2)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test1->showMe
object(test2)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test2->display
object(test2)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
test1->display
object(test2)(1) {
["a"]=>
int(0)
}
--------------------------------------------------------------------------------
0
test1->setA
object(test2)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test2->showMe
object(test2)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test1->showMe
object(test2)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test2->display
object(test2)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test1->display
object(test2)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
1
test1->callMe
object(test2)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test3->showMe
object(test2)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test2->showMe
object(test2)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test1->showMe
object(test2)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test2->display
object(test2)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
test1->display
object(test2)(1) {
["a"]=>
int(1)
}
--------------------------------------------------------------------------------
1
test1->setA
object(test2)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
test2->showMe
object(test2)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
test1->showMe
object(test2)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
test2->display
object(test2)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
test1->display
object(test2)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
2
test1->callMe
object(test2)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
test3->showMe
object(test2)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
test2->showMe
object(test2)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
test1->showMe
object(test2)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
test2->display
object(test2)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
test1->display
object(test2)(1) {
["a"]=>
int(2)
}
--------------------------------------------------------------------------------
*/
?>
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/?id=19376&edit=1