Hello Larry, Stefan, and Nicolas!
Thanks for the responses.
>>> Why were constants left out of traits previously
>> That!
> So, my working assumption is: it wasn’t something I really thought about.
From what I've read in the old ML archives of discussions on introducing
traits to PHP, perhaps constants simply were not among the considerations.
The phrase "constants" is rarely even mentioned in the discussion.
>> why the default value of a const (and a property) could not be changed
>> by the class importing the trait?
My answer to this question is 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.
Based on my limited understanding, let me briefly summarize the story.
Please point out if anything is incorrect.
First, it should be noted that in the original trait paper, the trait has only
behavior and no state, thereby avoiding the state conflict problem in
diamond inheritance. In the original trait paper, it is assumed that the state
is provided on the composing class side and accessed from the trait
through the accessor [1]. With this pure approach in mind, PHP allows
abstract methods to be declared in the trait, and the composing class
implements the requested accessors.
The problem with this pure approach is obvious: there is too much
boilerplate in creating and using traits. Traits provide class components,
and serious class components will often want to access some state.
During the initial discussions, many messages were sent to internals about
whether to allow properties in traits, and what form this should take.
By the way, historically, there have been two typical approaches to the
diamond inheritance state collision problem: one is to merge the state of
the common ancestor, and the other is to have independent state for each
common ancestor in the separate "path". Since different use cases require
one or the other, programming languages sometimes have features that
allow programmers to use these two methods selectively, such as virtual
inheritance in C++.
Where having state becomes tricky is when the diamond problem occurs.
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 independent state, that default will work fine for half of the use cases.
PHP strikes a balance in this problem, allowing traits to define properties,
and choosing to deal with conflicts by merging states, and also marking
any conflicting definitions with different visibility or default values as an
error, as a sign of an unintended name conflict [2].
This is how PHP came to have properties in traits in its current form; I
believe that the story of having data definitions instead of behaviors in
traits have barely settled itself, and the story of constant definitions was
simply forgotten or put on the back burner.
While not the main topic, current PHP does not yet provide a way to allow
common ancestors to have independent states. There are several
references to Stateful Traits in older discussions[3]. Stateful Traits default
to trait state as trait local, but allow the programmer to selectively use
merge behavior as needed. On the contrary, since PHP defaults to merge
behavior, there may be a future extension that allows trait local to be
explicitly declared. This option has even been mentioned in the old
discussions, but it has not caught the attention of many people and has
been on hold for more than a decade [4]. Perhaps it is time to reconsider
this also.
>> And I'd also be happy to see an implementation of this before voting
Yeah of course! It is generally working on my end, and I'll send PR within
a few days after adding a few more minor test cases.
[1] https://dl.acm.org/doi/10.1145/1119479.1119483
[2] https://externals.io/message/51007#51072
[3] https://link.springer.com/chapter/10.1007/978-3-540-71836-9_4
[4] https://externals.io/message/35800
Thanks!
--
Shinji Igarashi
2022年6月23日(木) 2:39 Stefan Marr <php@stefan-marr.de>: