From a6338d747762e36e01061eae19aadca4167375b6 Mon Sep 17 00:00:00 2001 From: Larry Garfield Date: Sat, 21 Nov 2020 19:50:13 +0000 Subject: [PATCH] Update constructor documentation to include constructor promotion. git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@351474 c90b9560-bf6c-de11-be94-00142212c4b1 --- language/oop5/decon.xml | 190 +++++++++++++++++++++++++++++++++------- 1 file changed, 159 insertions(+), 31 deletions(-) diff --git a/language/oop5/decon.xml b/language/oop5/decon.xml index 37467813da..a8222a9f16 100644 --- a/language/oop5/decon.xml +++ b/language/oop5/decon.xml @@ -10,7 +10,7 @@ mixedvalues"" - PHP 5 allows developers to declare constructor methods for classes. + PHP allows developers to declare constructor methods for classes. Classes which have a constructor method call this method on each newly-created object, so it is suitable for any initialization that the object may need before it is used. @@ -26,7 +26,7 @@ - using new unified constructors + Constructors in inheritance - - For backwards compatibility with PHP 3 and 4, if PHP cannot find a - __construct() function for a given - class, it will - search for the old-style constructor function, by the name of the class. - Effectively, it means that the only case that would have compatibility - issues is if the class had a method named - __construct() which was used for - different semantics. - - - - - Old style constructors are DEPRECATED in PHP 7.0, and - will be removed in a future version. You should always use - __construct() in new code. - - Unlike with other methods, PHP will not generate an E_STRICT level error message when @@ -86,28 +67,175 @@ $obj = new OtherSubClass(); than the parent __construct() method has. - As of PHP 5.3.3, methods with the same name as the last element of a - namespaced class name will no longer be treated as constructor. This - change doesn't affect non-namespaced classes. + Constructors are ordinary methods which are called during the instantiation of their + corresponding object. As such, they may define an arbitrary number of arguments, which + may be required, may have a type, and may have a default value. Constructor arguments + are called by placing the arguments in parentheses after the class name. - Constructors in namespaced classes + Using constructor arguments x = $x; + $this->y = $y; } } + +// Pass both parameters. +$p1 = new Point(4, 5); +// Pass only the required parameter. $y will take its default value of 0. +$p2 = new Point(4); +// With named parameters (as of PHP 8.0): +$p3 = new Point(y: 5, x: 4); ?> ]]> - + + If a class has no constructor, or the constructor has no required arguments, the parentheses + may be omitted. + + + Old-style constructors + + Prior to PHP 8.0.0, classes in the global namespace will interpret a method named + the same as the class as an old-style constructor. That syntax is deprecated, + and will result in an E_DEPRECATED error but still call that function as a constructor. + If both __construct() and a same-name method are + defined, __construct() will be called. + + + In namespaced classes, or any class as of PHP 8.0.0, a method named + the same as the class never has any special meaning. + + Always use __construct() in new code. + + + + Constructor Promotion + + As of PHP 8.0.0, constructor parameters may also be promoted to correspond to an + object property. It is very common for constructor parameters to be assigned to + a property in the constructor but otherwise not operated upon. Constructor promotion + provides a short-hand for that use case. The example above could be rewritten as the following. + + + Using constructor property promotion + + + + + + When a constructor argument includes a visibility modifier, PHP will interpret it as + both an object property and a constructor argument, and assign the argument value to + the property. The constructor body may then be empty or may contain other statements. + Any additional statements will be executed after the argument values have been assigned + to the corresponding properties. + + + Not all arguments need to be promoted. It is possible to mix and match promoted and not-promoted + arguments, in any order. Promoted arguments have no impact on code calling the constructor. + + + + Object properties may not be typed callable due to engine ambiguity that would + introduce. Promoted arguments, therefore, may not be typed callable either. Any + other type declaration is permitted, however. + + + + + + Attributes placed on a promoted constructor argument will be replicated to both the property + and argument. + + + + + Static creation methods + + PHP only supports a single constructor per class. In some cases, however, it may be + desirable to allow an object to be constructed in different ways with different inputs. + The recommended way to do so is by using static methods as constructor wrappers. + + + Using static creation methods + +id = $id; + $this->name = $name; + } + + public static function fromBasicData(int $id, string $name): static { + $new = new static($id, $name); + return $new; + } + + public static function fromJson(string $json): static { + $data = json_decode($json); + return new static($data['id'], $data['name']); + } + + public static function fromXml(string $xml): static { + // Put your own logic here. + $data = convert_xml_to_array($xml); + $new = new static(); + $new->id = $data['id']; + $new->name = $data['name']; + return $new; + } +} + +$p1 = Product::fromBasicData(5, 'Widget'); +$p2 = Product::fromJson($some_json_string); +$p3 = Product::fromXml($some_xml_string); +]]> + + + + The constructor may be made private or protected to prevent it from being called externally. + If so, only a static method will be able to instantiate the class. Because they are in the + same class definition they have access to private methods, even if not of the same object + instance. The private constructor is optional and may or may not make sense depending on + the use case.. + + + The three public static methods then demonstrate different ways of instantiating the object. + + + fromBasicData() takes the exact parameters that are needed, then creates the + object by calling the constructor and returning the result. + fromJson() accepts a JSON string and does some pre-processing on it itself + to convert it into the format desired by the constructor. It then returns the new object. + fromXml() accepts an XML string, preprocesses it, and then creates a bare + object. The constructor is still called, but as all of the parameters are optional the method + skips them. It then assigns values to the object properties directly before returning the result. + + + In all three cases, the static keyword is translated into the name of the class the code is in. + In this case, Product. + + + Destructor