rfc:constants_in_traits
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
rfc:constants_in_traits [2022/06/30 23:14] – sji | rfc:constants_in_traits [2022/08/04 19:17] (current) – Move the status to implemented sji | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== PHP RFC: Constants in Traits ====== | ====== PHP RFC: Constants in Traits ====== | ||
- | * Version: 0.1 | + | * Version: 0.2.1 |
* Date: 2022-06-21 | * Date: 2022-06-21 | ||
* Author: Shinji Igarashi< | * Author: Shinji Igarashi< | ||
- | * Status: | + | * Status: |
* Implementation: | * Implementation: | ||
* First Published at: http:// | * First Published at: http:// | ||
Line 40: | Line 40: | ||
<code php> | <code php> | ||
- | intertface | + | interface |
public const FLAG_1 = 1; | public const FLAG_1 = 1; | ||
public function doFoo(int $flags): void; | public function doFoo(int $flags): void; | ||
Line 66: | Line 66: | ||
trait Foo { | trait Foo { | ||
public const FLAG_1 = 1; | public const FLAG_1 = 1; | ||
- | | + | |
+ | private const FLAG_3 | ||
public function doFoo(int $flags): void { | public function doFoo(int $flags): void { | ||
Line 74: | Line 75: | ||
if ($flags & self:: | if ($flags & self:: | ||
echo 'Got flag 2'; | echo 'Got flag 2'; | ||
+ | } | ||
+ | if ($flags & self:: | ||
+ | echo 'Got flag 3'; | ||
} | } | ||
} | } | ||
Line 218: | Line 222: | ||
CONSTANT as private; | CONSTANT as private; | ||
} | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Can be used in Enum ==== | ||
+ | Enumerations can use traits having constants, which behave as if the constants were defined within the enumeration. | ||
+ | |||
+ | <code php> | ||
+ | trait T { | ||
+ | private const CONSTANT = 42; | ||
+ | } | ||
+ | |||
+ | // OK | ||
+ | enum E: int { | ||
+ | use T; | ||
+ | |||
+ | case CaseA = self:: | ||
} | } | ||
</ | </ | ||
Line 272: | Line 292: | ||
While the main use case of trait methods is to be invoked from outside of the trait, the main use case of a trait constant is to serve as a member that is referenced by methods in the trait. Therefore, the same way of conflict resolution as for methods is not very useful. | While the main use case of trait methods is to be invoked from outside of the trait, the main use case of a trait constant is to serve as a member that is referenced by methods in the trait. Therefore, the same way of conflict resolution as for methods is not very useful. | ||
- | Currently, PHP has held off on better conflict resolution for trait properties for the last decade, and simply marks multiple incompatible definitions as errors, as an obvious sign of a mistake. One idea to address this issue is to introduce new visibility "trait local" that are only accessible within a given trait [[https:// | + | Currently, PHP has held off on better conflict resolution for trait properties for the last decade, and simply marks multiple incompatible definitions as errors, as an obvious sign of a mistake. One idea to address this limitation |
Constants in PHP can hold state through object constants and are more similar to properties than methods. Both constants and properties should have the same style of conflict resolution. Therefore, for now, this RFC only proposes that trait constants have the same restrictions as properties. | Constants in PHP can hold state through object constants and are more similar to properties than methods. Both constants and properties should have the same style of conflict resolution. Therefore, for now, this RFC only proposes that trait constants have the same restrictions as properties. | ||
==== Why are those compatibility checks performed on properties in the first place ==== | ==== Why are those compatibility checks performed on properties in the first place ==== | ||
- | It's basically a way to deal with state conflicts in the diamond problem. | + | It's basically a way to deal with state conflicts in multiple inheritance. |
If we were to allow some " | If we were to allow some " | ||
Line 283: | Line 303: | ||
There can be more than one policy for handling state conflicts, and PHP has implemented one restricted approach for now and has not yet addressed another policy after that. | There can be more than one policy for handling state conflicts, and PHP has implemented one restricted approach for now and has not yet addressed another policy after that. | ||
- | It should be noted that in the original trait paper, traits have only behavior and no state, thereby avoiding the state conflict problem in diamond | + | It should be noted that in the original trait paper, traits have only behavior and no state, thereby avoiding the state conflict problem in multiple |
- | Historically, | + | Historically, |
Where having a state becomes tricky is when conflicts occur. If there are no conflicts, it does not matter if a trait has state. And even if there is a conflict, if the programming language defaults to either merge or having an independent state, that default will work fine for half of the use cases. | Where having a state becomes tricky is when conflicts occur. If there are no conflicts, it does not matter if a trait has state. And even if there is a conflict, if the programming language defaults to either merge or having an independent state, that default will work fine for half of the use cases. | ||
Line 310: | Line 330: | ||
A survey of the 1149 packages on packagist shows that at least 222 locations in 26 packages use this feature for trait methods. | A survey of the 1149 packages on packagist shows that at least 222 locations in 26 packages use this feature for trait methods. | ||
- | We refrain from judging whether this is large or small, but there are probably cases where it is more convenient for classes to be able to decide which members to expose. | + | We refrain from judging whether this is large or small, but there are probably cases where it is more convenient for composing |
We do not preclude the future introduction of this feature, but for the sake of simplicity, we do not include it in this RFC. | We do not preclude the future introduction of this feature, but for the sake of simplicity, we do not include it in this RFC. | ||
Line 327: | Line 347: | ||
==== Rust ==== | ==== Rust ==== | ||
- | Rust has associated constants. | + | Rust has associated constants. |
==== C++ ==== | ==== C++ ==== | ||
- | In C++, multiple inheritance is possible, and constants in PHP can be defined as static | + | In C++, multiple inheritance is possible, and equivalents of constants in PHP can be defined as static |
==== Scala ==== | ==== Scala ==== | ||
Line 336: | Line 356: | ||
- | ===== Proposed Voting Choices | + | ===== Vote ===== |
- | A 2/3 majority is needed for this RFC to pass. Voting | + | A 2/3 majority is needed for this RFC to pass. Voting |
+ | |||
+ | <doodle title=" | ||
+ | * Yes | ||
+ | * No | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== Future Scope ===== | ||
+ | |||
+ | ==== Trait Local ==== | ||
+ | Since constants and properties of traits are primarily intended to be referenced from within traits, it is more useful to be able to restrict the scope to trait local and prevent conflicts in the first place. This is also true for methods that presume references from inside the trait itself, such as recursions. | ||
+ | |||
+ | Stateful Traits [[https:// | ||
+ | |||
+ | ==== Requiring specific interfaces or classes on traits ==== | ||
+ | Hack can require that the composing class of a trait be a derived class of a specific class or an implementation of a specific interface [[https:// | ||
+ | |||
+ | At the same time, Hack also allows to implement interfaces from traits. That is, if a class C uses a trait T that implements an interface I, then C is a subtype of I [[https:// | ||
+ | |||
+ | These can be other ways to tie properties or constants to traits, and this RFC does not preclude future implementation of any of them. | ||
===== Patches and Tests ===== | ===== Patches and Tests ===== | ||
Line 364: | Line 404: | ||
* [[https:// | * [[https:// | ||
* [[https:// | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
* https:// | * https:// | ||
- | + |
rfc/constants_in_traits.1656630871.txt.gz · Last modified: 2022/06/30 23:14 by sji