rfc:generics

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:generics [2016/04/20 08:56] – Fix mistake in traits, add draft section for nested types orolynrfc:generics [2018/06/02 17:33] (current) – add github link mindplay
Line 6: Line 6:
   * Status: Draft   * Status: Draft
   * First Published at: http://wiki.php.net/rfc/generics   * First Published at: http://wiki.php.net/rfc/generics
 +
 +**NOTE:** a newer version of this RFC may be under development [[https://github.com/mindplay-dk/php-generics-rfc|on GitHub]].
  
 ===== Introduction ===== ===== Introduction =====
Line 178: Line 180:
 Any valid PHP type-hint may be used as an upper bound, including simple types like ''int'', ''float'', ''bool'', ''string'' and ''object''. (Omission of an upper bound effectively means ''mixed'' in general PHP terms, though we are not proposing the ability to explicitly type-hint as ''mixed'', which isn't supported by PHP.) Any valid PHP type-hint may be used as an upper bound, including simple types like ''int'', ''float'', ''bool'', ''string'' and ''object''. (Omission of an upper bound effectively means ''mixed'' in general PHP terms, though we are not proposing the ability to explicitly type-hint as ''mixed'', which isn't supported by PHP.)
  
-Note that the choice of the keyword ''is'' to indicate upper bounds is based on the rejection of perhaps more obvious alternatives - repurposing the ''extends'' or ''implements'' keywords would be misleading, since they would work precisely the same way; worse, permitting both keywords would render consumer code invalid if an upper bound type provided by a library is refactored between class and interface. Repurposing ''instanceof'' would also be misleading, since the upper bound is checking the type-hint, not an instance.+Note that the choice of the keyword ''is'' to indicate upper bounds is based on the rejection of perhaps more obvious alternatives - repurposing the ''extends'' or ''implements'' keywords would be misleading, since they would work precisely the same way; worse, permitting both keywords would render consumer code invalid if an upper bound type provided by a library is refactored between class and interface. Repurposing ''instanceof'' would also be misleading, since the upper bound is checking the type-hint, not an instance. Furthermore, we don't want this to collide with possible future mixed scalar types, such as ''number'' or ''scalar'', neither of which make sense in conjunction with either ''extends'' or ''implements''. (If a reserved ''is'' keyword is undesirable for other reasons, a simple '':'' is likely a better alternative than overloading the meaning of an existing keyword.)
  
 == Bounds Checking == == Bounds Checking ==
Line 289: Line 291:
 The first example is able to infer the type argument ''T'' as ''Hat'', because the type alias was used to type-hint the argument given for the ''$content'' parameter. The first example is able to infer the type argument ''T'' as ''Hat'', because the type alias was used to type-hint the argument given for the ''$content'' parameter.
  
-The second example results in a ''TypeError'', because the type parameter ''T'' was explicitly defined as ''string''. (Note that, if we had not used ''declare(strict_types=1)'', and if ''Box'' had implemented ''__toString()'', this would have been acceptable, due to the default behavior of weak scalar type-checking.)+The second example results in a ''TypeError'', because the type parameter ''T'' was explicitly defined as ''string''. (Note that, if we had not used ''declare(strict_types=1)'', and if ''Box'' had implemented ''<nowiki>__toString()</nowiki>'', this would have been acceptable, due to the default behavior of weak scalar type-checking.)
  
 Note the addition of ''func_type_args()'', which returns a list of type-hints pertaining to the current generic function call or constructor invocation. This complements ''func_get_args()'' by providing the list of type-arguments as fully-qualified class-names. Note the addition of ''func_type_args()'', which returns a list of type-hints pertaining to the current generic function call or constructor invocation. This complements ''func_get_args()'' by providing the list of type-arguments as fully-qualified class-names.
Line 327: Line 329:
  
 The same applies when overriding constructors and static methods. The same applies when overriding constructors and static methods.
 +
 +==== Generic Constructors ====
 +
 +Constructors may accept arbitrary type-arguments, just like any other method, e.g.:
 +
 +<code php>
 +class Hello<T1>
 +{
 +    public function __construct<T1,T2>()
 +    {
 +        // ...
 +    }
 +}
 +</code>
 +
 +In other words, the constructor may accept more type-arguments than those affecting the type.
  
 ==== Generic Closures ==== ==== Generic Closures ====
Line 365: Line 383:
  
 TODO: decide whether or not [[https://en.wikipedia.org/wiki/Bounded_quantification|bounded polymorphism]] should be supported. TODO: decide whether or not [[https://en.wikipedia.org/wiki/Bounded_quantification|bounded polymorphism]] should be supported.
 +
 +=== Multiple Constraints ===
 +
 +TODO: decide whether or not multiple constraints should be supported, e.g. with a Java-like syntax:
 +
 +<code php>
 +class A<T> where T is T1, T is T2 {
 +    // ...
 +}
 +</code>
 +
 +This may relate to the [[https://wiki.php.net/rfc/union_types|union types RFC]] - if implemented, it may be more natural to expect support for union types as bounds.
  
 ==== Autoloading ==== ==== Autoloading ====
rfc/generics.txt · Last modified: 2018/06/02 17:33 by mindplay