php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #66627 Static variables in inherited classes not explained
Submitted: 2014-02-02 23:52 UTC Modified: 2021-03-03 18:18 UTC
From: kulakov74 at yandex dot ru Assigned:
Status: Verified Package: Documentation problem
PHP Version: 5.4.24 OS: Any
Private report: No CVE-ID: None
 [2014-02-02 23:52 UTC] kulakov74 at yandex dot ru
Description:
------------
Studying Traits (php.net/traits), I found the example (#9) with static variables which produced different results from what I expected, that is the static variable $c was not shared in the 2 classes using the trait Counter. I tried some tests with traits and classes and came to the conclusion that the behaviour is correct but not documented well in the case of class inheritance. Static variables are really tied to the function they are declared in but if the function is a class method and the class is inherited from, the method may be internally duplicated (I believe it's implemented this way) to the child class where it actually becomes a different (albeit identical) method hence it holds its own copy of the same static variable. By duplicating I mean the resulting behavior is just like the methods are really declared in the child. 

In my tests I found out the following:
-A static variable in a class method acts just like one in a global function (that's almost obvious). 
-If the class is extended then all its methods except the constructor (& destructor) and the private methods are internally duplicated to the child. Public and protected methods can be called in the child hence they need to be duplicated in it. Constructors and privates are specific to the base class hence their static vars are shared between all children. 

Traits exhibit similar behavior. This is my understanding of the behavior, it may be wrong but anyway the behavior should explained in more detail in the manual. 

Related bugs: 
https://bugs.php.net/bug.php?id=39713
https://bugs.php.net/bug.php?id=62547
https://bugs.php.net/bug.php?id=63454



Test script:
---------------
class B{
	function __construct(){static $con=0; $con++; echo(get_class($this)."::con:$con; ");}
	function pub(){static $pub=0; $pub++; echo(get_class($this)."::pub:$pub; ");}
	function test(){$this->prv(); $this->prot();}
	private function prv(){static $prv=0; $prv++; echo(get_class($this)."::prv:$prv; ");}
	protected function prot(){static $prot=0; $prot++; echo(get_class($this)."::prot:$prot; ");}
}
class C1 extends B{} class C2 extends B{}

$B1=new B; $B2=new B; $C1=new C1; $C2=new C2; echo("\n");
$B1->pub(); $B2->pub(); $B1->pub(); $B2->pub(); echo("\n");
$C1->pub(); $C1->pub(); $C2->pub(); $C2->pub(); echo("\n");
$B1->test(); $B2->test(); echo("\n");
$C1->test(); $C1->test(); $C2->test(); $C2->test(); echo("\n");


Expected result:
----------------
---

Actual result:
--------------
B::con:1; B::con:2; C1::con:3; C2::con:4; 
B::pub:1; B::pub:2; B::pub:3; B::pub:4; 
C1::pub:1; C1::pub:2; C2::pub:1; C2::pub:2; 
B::prv:1; B::prot:1; B::prv:2; B::prot:2; 
C1::prv:3; C1::prot:1; C1::prv:4; C1::prot:2; C2::prv:5; C2::prot:1; C2::prv:6; C2::prot:2; 


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-03-03 18:18 UTC] cmb@php.net
-Status: Open +Status: Verified
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 14:01:29 2024 UTC