rfc:static_variable_inheritance

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
rfc:static_variable_inheritance [2021/02/23 13:45] – created nikicrfc:static_variable_inheritance [2021/04/28 15:12] (current) nikic
Line 2: Line 2:
   * Date: 2021-02-23   * Date: 2021-02-23
   * Author: Nikita Popov <nikic@php.net>   * Author: Nikita Popov <nikic@php.net>
-  * Status: Under Discussion+  * Status: Implemented
   * Target Version: PHP 8.1   * Target Version: PHP 8.1
 +  * Implementation: https://github.com/php/php-src/pull/6719
  
 ===== Introduction ===== ===== Introduction =====
Line 28: Line 29:
 When ''A::counter()'' is inherited into class ''B'', a separate set of static variables is used, and ''A::counter()'' and ''B::counter()'' will manage an independent counter. When ''A::counter()'' is inherited into class ''B'', a separate set of static variables is used, and ''A::counter()'' and ''B::counter()'' will manage an independent counter.
  
-This RFC proposed to instead have only one set of static variables per method, regardless of whether it is inherited:+This RFC proposes to instead have only one set of static variables per method, regardless of whether it is inherited:
  
 <PHP> <PHP>
Line 145: Line 146:
 var_dump(B::counter()); // int(3) var_dump(B::counter()); // int(3)
 var_dump(B::counter()); // int(4) var_dump(B::counter()); // int(4)
 +</PHP>
 +
 +The behavior does not depend on whether the method is static or not:
 +
 +<PHP>
 +class A {
 +    public function counter() {
 +        static $i = 0;
 +        return ++$i;
 +    }
 +}
 +class B extends A {}
 + 
 +var_dump((new A)->counter()); // int(1)
 +var_dump((new A)->counter()); // int(2)
 +var_dump((new B)->counter()); // int(3)
 +var_dump((new B)->counter()); // int(4)
 </PHP> </PHP>
  
Line 168: Line 186:
 </PHP> </PHP>
  
-This is consistent with the general semantics of traits as "compiler-assisted copy and paste". The code behaves as-if the method definition was literally pasted into both classes. This is also consistent with the behavior of static properties in traits.+This is consistent with the general semantics of traits as "compiler-assisted copy and paste". The code behaves as-if the method definition was literally pasted into both classes. This is also consistent with the behavior of static properties in traits. Additionally, it ensures that if a method is used multiple times under different aliases, they will all have distinct static variables.
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
  
-The behavior of static variables in methods changes as described above. The current behavior of static variables is not documented. I consider it to be borderline buggy.+The behavior of static variables in methods changes as described above. The current behavior of static variables is not documented. I consider it to be borderline buggy. Typical memoization use-cases for static variables will not be affected (apart from memoizing more effectively). 
 + 
 +Code that intentionally relies on the current behavior can be made compatible by indexing the static variable by the class name: 
 + 
 +<PHP> 
 +class A { 
 +    public function counter() { 
 +        // This code works both for static and non-static methods. 
 +        static $counters = []; 
 +        $counters[static::class] ??= 0; 
 +        return ++$counters[static::class]; 
 +    } 
 +
 +class B extends A { 
 +
 + 
 +var_dump((new A)->counter()); // int(1) 
 +var_dump((new A)->counter()); // int(2) 
 +var_dump((new B)->counter()); // int(1) 
 +var_dump((new B)->counter()); // int(2) 
 +</PHP> 
 + 
 +This code will work the same way both before and after the proposed behavior change.
  
 ===== Vote ===== ===== Vote =====
  
-Yes/No.+Voting started 2021-04-14 and ended 2021-04-28. 
 + 
 +<doodle title="Change static variable inheritance as proposed?" auth="nikic" voteType="single" closed="true"> 
 +   Yes 
 +   No 
 +</doodle>
rfc/static_variable_inheritance.1614087950.txt.gz · Last modified: 2021/02/23 13:45 by nikic