rfc:class_and_interface_name_types

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:class_and_interface_name_types [2017/04/29 14:07] – Remove classlike and interface ajfrfc:class_and_interface_name_types [2017/09/22 13:28] (current) – external edit 127.0.0.1
Line 16: Line 16:
   - If the value is not a string, reject it.   - If the value is not a string, reject it.
   - If there is no currently-loaded class, interface, or trait with the name given by the value, attempt to autoload it.   - If there is no currently-loaded class, interface, or trait with the name given by the value, attempt to autoload it.
-  - If there is now no currently-loaded class or interface (as appropriate) with the name given by the value, reject the value.+  - If there is now no currently-loaded class or interface with the name given by the value, reject the value.
   - Otherwise, accept the value.   - Otherwise, accept the value.
 +
 +As a parameter type, it would permit default values of <php>NULL</php> (to make the parameter null) and constant strings (including <php>::class</php> syntax).
  
 A simple example of usage: A simple example of usage:
Line 24: Line 26:
 <?php <?php
  
-function accepts_class(class $class) {+function accepts_class(class $class = stdClass::class) {
     var_dump($class);     var_dump($class);
 } }
  
-accepts_class(stdClass::class);    // works +accepts_class();                   // string(8) "stdClass" 
-accepts_class("stdClass");         // also works +accepts_class(stdClass::class);    // string(8) "stdClass" 
-accepts_class(ArrayAccess::class); // interfaces are also accepted+accepts_class("stdClass");         // string(8) "stdClass" 
 +accepts_class(ArrayAccess::class); // string(11) "ArrayAccess"
 accepts_class("nonexistant");      // Fatal error: Uncaught TypeError: Argument 1 passed to accepts_class() must be of the type class, string given… accepts_class("nonexistant");      // Fatal error: Uncaught TypeError: Argument 1 passed to accepts_class() must be of the type class, string given…
 </code> </code>
  
-===== Background and Rationale =====+===== Rationale and Points for Discussion ===== 
 + 
 +==== Naming: "class" vs "classname"? ==== 
 + 
 +This RFC currently proposes to call this type declaration <php>class</php>. Hack, PHP's sister language, already [[https://docs.hhvm.com/hack/types/type-system#type-aliases__classname|includes a similar type for class names]], but calls it ''classname'' instead. 
 + 
 +The name <php>class</php> has a few advantages: 
 + 
 +  * It is short 
 +  * It is already a reserved word, so introducing it requires no backwards-incompatibility break 
 +  * It resembles the <php>::class</php> syntax for obtaining the name of a class 
 +  * It avoids the redundancy of saying "name", given PHP does not represent classes as values in any other way (excepting reflection) 
 +  * It aligns with how PHP treats a class and its fully-qualified name the same in several places (e.g. <php>new $class</php> and <php>$class::$property</php>
 + 
 +However, there are also arguments in favour of ''classname'': 
 + 
 +  * It conveys more directly that the value is a string containing a class name 
 +  * It is already in use by Hack, so using this would prevent further divergence between Hack and PHP 
 + 
 +==== Should "class" include only classes, or both classes and interfaces? ==== 
 + 
 +This RFC currently proposes that there would be a single new type, <php>class</php>, which would accept the names of both classes and interfaces. There might, however, be a case to be made for accepting only classes, and/or having a separate type for interface names (<php>interface</php>, say), or even a third type for accepting both classes and interfaces. 
 + 
 +Having <php>class</php> accept both classes and interfaces has a few arguments in its favour: 
 + 
 +  * It limits the number of new types that are introduced (one versus two or three) 
 +  * It aligns with the internal ''zend_parse_parameters()'' type ''"C"'', used by some functions in the PHP standard library, which likewise accepts both class and interface names 
 +  * It aligns with how <php>::class</php> works for both class and interface names 
 +  * Interfaces are essentially glorified abstract classes 
 +  * PHP internally represents interfaces as a kind of class 
 +  * Reflection represents interfaces as a kind of class 
 +  * The type declaration need not be perfectly fine-grained, as the function body can check if the value given is an interface itself 
 + 
 +That being said, there are also arguments in favour of <php>class</php> accepting only classes: 
 + 
 +  * Class and interface definitions use different keywords 
 +  * <php>class_exists()</php> treats interfaces as non-existent 
 +  * It might be surprising to see the name of an //interface// be passed as an argument to a parameter typed "<php>class</php>" 
 + 
 +There is an advantage to a separate <php>interface</php> type, insofar as having PHP distinguish classes and interfaces in type declarations makes for clearer function signatures and avoids potential manual testing of whether a value is class or an interface. 
 + 
 +If there was a separate <php>interface</php> type, there would be an argument for having the <php>class</php> type also accept interfaces, since classes are a superset of interfaces, and classes can subclass (“implement”) interfaces, but not the other way around.
  
-FIXME: Talk about Hack, and what it does differently?+If none of these approaches are palatablethere could be a //third// type accepting both classes and interfaces, perhaps named ''classlike''. However, this might be reaching the point of diminishing returns.
  
-FIXME: Justify “classlike”/class/interface distinction?+All the possibilities in this section can and have been implemented provisionally, and the branch on GitHub contains all of them in its commit history.
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
Line 64: Line 108:
 There is a patch here which contains tests: https://github.com/php/php-src/compare/master...hikari-no-yume:class_type_declaration There is a patch here which contains tests: https://github.com/php/php-src/compare/master...hikari-no-yume:class_type_declaration
  
-It does not yet handle inheritance concerns.+The commits for versions with multiple new types do not handle inheritance concerns.
  
 There is not yet a pull request. There is not yet a pull request.
rfc/class_and_interface_name_types.1493474860.txt.gz · Last modified: 2017/09/22 13:28 (external edit)