rfc:default_ctor

Differences

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

Link to this comparison view

Next revision
Previous revision
rfc:default_ctor [2014/11/06 23:20] – created stasrfc:default_ctor [2018/03/01 23:52] (current) – RFC was declined carusogabriel
Line 3: Line 3:
   * Date: 2014-11-05   * Date: 2014-11-05
   * Author: Stas Malyshev, stas@php.net   * Author: Stas Malyshev, stas@php.net
-  * Status: Draft +  * Status: Declined 
   * First Published at: http://wiki.php.net/rfc/default_ctor   * First Published at: http://wiki.php.net/rfc/default_ctor
  
 ===== Introduction ===== ===== Introduction =====
-This RFC proposes to introduce the concept of default constructors into PHP. The meaning of it is that whatever is the parent class, child class can always call %%parent::__construct()%% and this call will never fail. In fact, PHP, in some meaning, already has default constructors, as you can write %%$a = new Foo()%% even if class Foo does not define a constructor. However, that default "null" constructor which can be invoked with new can not be invoked directly via method call. This RFC proposes that the call to %%parent::__construct()%% will always succeed.+This RFC proposes to introduce the concept of default constructors into PHP. The meaning of it is that whatever is the parent class, child class can always call %%parent::__construct()%% and this call will never fail. In fact, PHP, in some meaning, already has default constructors, as you can write %%$a = new Foo()%% even if class Foo does not define a constructor. However, that default "null" constructor which can be invoked with new can not be invoked directly via method call. This RFC proposes that the call to %%parent::__construct()%% will always work just as "new Foo" always works, regardless of ctor being defined.
  
 ===== Proposal ===== ===== Proposal =====
Line 58: Line 58:
 The call to the %%parent::__construct()%% will always succeed, provided the current class has any parent class, if the constructor there is not defined. The call to the %%parent::__construct()%% will always succeed, provided the current class has any parent class, if the constructor there is not defined.
  
-The call to the parent constructor would be a regular function call, which means it will evaluate its arguments, if provided, and produce all other effects that the function call produceds. However, the call would return immediately without having any other effects.+The call to the parent constructor would be a regular function call, which means it will evaluate its arguments, if provided, and produce all other effects that the function call produces. However, the call would return immediately without having any other effects.
  
 ===== Implementation ===== ===== Implementation =====
Line 64: Line 64:
 There can be two approaches to implementing this functionality: There can be two approaches to implementing this functionality:
  
-1. Creating %%__construct%% method behind the scenes for all classes that do not have one defined. +  - Creating %%__construct%% method behind the scenes for all classes that do not have one defined. 
-2. Detecting call to %%arent::__construct%% and making it succeed even if there is no underlying method defined.+  Detecting call to %%parent::__construct%% and making it succeed even if there is no underlying method defined.
  
 This RFC chooses the second approach, because the first one will result in much larger refactoring of the engine, due to the fact that right now class, interface and trait tables are handled in the same way, but ctor insertion needs to be performed only for classes, but not for others. So introducing it will require changing a lot of code everywhere we create classes or interfaces, to introduce the information needed to separate them. This RFC chooses the second approach, because the first one will result in much larger refactoring of the engine, due to the fact that right now class, interface and trait tables are handled in the same way, but ctor insertion needs to be performed only for classes, but not for others. So introducing it will require changing a lot of code everywhere we create classes or interfaces, to introduce the information needed to separate them.
  
-Also, it would change the actual method table, which will require either substantial changes to all reflection-relared functions (to skip the implicitly defined methods) or possible BC breaks where the actual method set of the class is not what the class creator expects.+Also, it would change the actual method table, which will require either substantial changes to all reflection-related functions (to skip the implicitly defined methods or to change assumptions about what would and would not be defined) or possible BC breaks where the actual method set of the class is not what the class creator expects.
  
 Also, this can lead to more subtle BC breaks. Consider this code: Also, this can lead to more subtle BC breaks. Consider this code:
Line 83: Line 83:
 Right now, in PHP, the call to bar() is not executed since Foo's ctor does not exist. However, if we change it so that Foo's ctor always exists, the call to bar() would be executed. Granted, this code does not have the best style, but there might be some code in the field, especially after multiple refactoring rounds, and changing how it works still will be a break. Right now, in PHP, the call to bar() is not executed since Foo's ctor does not exist. However, if we change it so that Foo's ctor always exists, the call to bar() would be executed. Granted, this code does not have the best style, but there might be some code in the field, especially after multiple refactoring rounds, and changing how it works still will be a break.
  
-The current implementation only changes how the %%parent::__construct()%% works (and only by enabling cases which did not work before) but does not change anything else, thus reducing the impact of the change. +The current implementation only changes how the %%parent::__construct()%% works (and only by enabling cases which did not work before) but does not change anything else, thus reducing the BC impact of the change.  
 + 
 +Also note that only "parent" calls are supported by this RFC, since this is the best practice (and in some languages, like Java, mandatory) to call the parent ctor. If instead the code does something else - like calling ctor from classes further up the hierarchy, etc. - the RFC does not change the existing behavior in that case. 
 + 
 +===== Other Methods ===== 
 + 
 +%%__construct%% is not the only method with this usage pattern, %%__destruct%% and %%__clone%% have essentially the same issue. So it can be said that the same arguments outlines above apply to these methods too and consequently the same functionality should be implemented for these methods. Thus, this RFC includes the implementation of the same functionality for them too.
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
  
-No backward incompatible changes, since it is highly improbably somebody's code relies on being unable to call %%parent::__construct%%.+No backward incompatible changes, since it is highly improbable that somebody's code relies on being unable to call %%parent::__construct%% and producing a fatal error. 
 + 
 +====== Interactions with __call ====== 
 + 
 +While using __call to dispatch magic methods is not a good idea, the dispatch would work with this RFC the same way it worked before, without any changes
  
 ===== Proposed PHP Version(s) ===== ===== Proposed PHP Version(s) =====
 This proposal is targeted for PHP 7. This proposal is targeted for PHP 7.
- 
-===== RFC Impact ===== 
  
 ===== Patches and Tests ===== ===== Patches and Tests =====
  
 +https://github.com/php/php-src/pull/990
 +
 +===== Voting =====
 +
 +Since this RFC changes the language semantics, the 2/3+1 vote majority is required for it to pass. The vote is a straight Yes/No vote. 
 +
 +<doodle title="Should PHP 7 have default constructor semantics as described in this proposal?" auth="stas" voteType="single" closed="true">
 +   * Yes
 +   * No
 +</doodle>
  
 +The vote concludes on the end of the day, PST, January 24th.
 ===== References ===== ===== References =====
  
-Java: http://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html +Java:  
-http://docs.oracle.com/javase/tutorial/java/IandI/super.html+  - http://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html 
 +  http://docs.oracle.com/javase/tutorial/java/IandI/super.html 
 +  - http://stackoverflow.com/questions/11379115/do-you-call-super-finalize-within-a-subclass
  
-C#: http://www.dotnetperls.com/default-constructor+C#:  
 +  - http://www.dotnetperls.com/default-constructor
 ===== Changelog ===== ===== Changelog =====
  
  * 2014-11-05 Started the RFC  * 2014-11-05 Started the RFC
  
rfc/default_ctor.1415316028.txt.gz · Last modified: 2017/09/22 13:28 (external edit)