Hi internals,
I'm currently trying to make sure that all internal Traversable classes
implement either Iterator or IteratorAggregate. This is a hard requirement
for userland classes, but internal classes can get away with implementing
only the internal get_iterator() mechanism. (
https://github.com/php/php-src/pull/5216)
One problem I ran into along the way is the SimpleXMLIterator class. A
naive person might think that there is some sanity left in this world, and
the hierarchy for SXE/SXI looks like this:
SimpleXMLElement implements IteratorAggregate
// where SimpleXMLElement::getIterator() returns:
SimpleXMLIterator implements Iterator
Of course, they would be wrong. The actual hierarchy is this:
SimpleXMLElement implements Traversable
SimpleXMLIterator extends SimpleXMLElement implements Iterator
The fact that SimpleXMLIterator extends SimpleXMLElement leaves me in a
tough spot, because it means SimpleXMLElement cannot be an
IteratorAggregate -- that would mean that SimpleXMLIterator implements both
IteratorAggregate and Iterator, which is not permissible.
It seems that it's also not possible to remove the "extends" without a
non-trivial backwards-compatibility break, because apparently writing
simplexml_load_string($str, 'SimpleXMLIterator') is a thing, which requires
SimpleXMLIterator to extend SimpleXMLElement (and possibly is the reason
why this was done in the first place.)
The only way out I see here is to lift the methods from SimpleXMLIterator
into SimpleXMLElement, make SimpleXMLElement implement Iterator itself, and
basically leave SimpleXMLIterator as a dummy extension of SimpleXMLElement.
Does that sound "reasonable"? Or rather, is there something more reasonable
that can be done?
Regards,
Nikita
OFFLIST
First one want to say but thanks and kudos for all you are doing for PHP.
Second, and so as not to hijack your thread or worse start a whole bike shedding debate on the list, I have been wanted to ask you some questions and I saw this as a good segue to ask your thoughts on traits vs. interfaces vs. extends.
Simply put I have found that to use a same-named trait+interface I can effectively achieve multiple inheritance, which is what it sounds like would help the scenario you have below. If we had multiple inheritance we could see much more fine-grain classes to inherit from (my traits+interfaces are fine grained) and that could make these kind of issues easier to deal with.
Note my thoughts here are very much influenced by Uncle Bob's blog post "'Interface' Considered Harmful":
https://blog.cleancoder.com/uncle-bob/2015/01/08/InterfaceConsideredHarmful.html
My questions are:
-
Internally in PHP, how different are traits implemented than classes, and ignoring what anyone's opinion would be on if we should do it, how technically feasible would it be to be able to "use {class_name}" in addition to the current "use {trait_name}?" (Or better yet "use class {class_name}")
-
Additionally, a class with only abstract methods is effectively an interface. How technically feasible would it be to be able to "implements {class_name}" in addition to the current "implements {interface_name}?" (Or better yet "implements class {class_name}")
-
Lastly, ignoring all the above, is there a technical reason we would not be able to allow:
Interfaces to declare static methods?
Traits to implement constants?
Interfaces to declare constants?
Thank you in advance for taking the time to read, consider and reply.
-Mike
P.S. Did you see/read this which I linked to one of your Github tickets:
https://mikeschinkel.me/2020/adding-delegation-to-php/
Any thoughts or feedback?
Hi internals,
I'm currently trying to make sure that all internal Traversable classes
implement either Iterator or IteratorAggregate. This is a hard requirement
for userland classes, but internal classes can get away with implementing
only the internal get_iterator() mechanism. (
https://github.com/php/php-src/pull/5216)One problem I ran into along the way is the SimpleXMLIterator class. A
naive person might think that there is some sanity left in this world, and
the hierarchy for SXE/SXI looks like this:SimpleXMLElement implements IteratorAggregate
// where SimpleXMLElement::getIterator() returns:
SimpleXMLIterator implements IteratorOf course, they would be wrong. The actual hierarchy is this:
SimpleXMLElement implements Traversable
SimpleXMLIterator extends SimpleXMLElement implements IteratorThe fact that SimpleXMLIterator extends SimpleXMLElement leaves me in a
tough spot, because it means SimpleXMLElement cannot be an
IteratorAggregate -- that would mean that SimpleXMLIterator implements both
IteratorAggregate and Iterator, which is not permissible.It seems that it's also not possible to remove the "extends" without a
non-trivial backwards-compatibility break, because apparently writing
simplexml_load_string($str, 'SimpleXMLIterator') is a thing, which requires
SimpleXMLIterator to extend SimpleXMLElement (and possibly is the reason
why this was done in the first place.)The only way out I see here is to lift the methods from SimpleXMLIterator
into SimpleXMLElement, make SimpleXMLElement implement Iterator itself, and
basically leave SimpleXMLIterator as a dummy extension of SimpleXMLElement.Does that sound "reasonable"? Or rather, is there something more reasonable
that can be done?Regards,
Nikita
Well, that did not work as intended...
OFFLIST
First one want to say but thanks and kudos for all you are doing for PHP.
Second, and so as not to hijack your thread or worse start a whole bike shedding debate on the list, I have been wanted to ask you some questions and I saw this as a good segue to ask your thoughts on traits vs. interfaces vs. extends.
Simply put I have found that to use a same-named trait+interface I can effectively achieve multiple inheritance, which is what it sounds like would help the scenario you have below. If we had multiple inheritance we could see much more fine-grain classes to inherit from (my traits+interfaces are fine grained) and that could make these kind of issues easier to deal with.
Note my thoughts here are very much influenced by Uncle Bob's blog post "'Interface' Considered Harmful":
• https://blog.cleancoder.com/uncle-bob/2015/01/08/InterfaceConsideredHarmful.html
My questions are:
Internally in PHP, how different are traits implemented than classes, and ignoring what anyone's opinion would be on if we should do it, how technically feasible would it be to be able to "use {class_name}" in addition to the current "use {trait_name}?" (Or better yet "use class {class_name}")
Additionally, a class with only abstract methods is effectively an interface. How technically feasible would it be to be able to "implements {class_name}" in addition to the current "implements {interface_name}?" (Or better yet "implements class {class_name}")
Lastly, ignoring all the above, is there a technical reason we would not be able to allow:
• Interfaces to declare static methods?
• Traits to implement constants?
• Interfaces to declare constants?Thank you in advance for taking the time to read, consider and reply.
-Mike
P.S. Did you see/read this which I linked to one of your Github tickets:
• https://mikeschinkel.me/2020/adding-delegation-to-php/
Any thoughts or feedback?
Hi internals,
I'm currently trying to make sure that all internal Traversable classes
implement either Iterator or IteratorAggregate. This is a hard requirement
for userland classes, but internal classes can get away with implementing
only the internal get_iterator() mechanism. (
https://github.com/php/php-src/pull/5216)One problem I ran into along the way is the SimpleXMLIterator class. A
naive person might think that there is some sanity left in this world, and
the hierarchy for SXE/SXI looks like this:SimpleXMLElement implements IteratorAggregate
// where SimpleXMLElement::getIterator() returns:
SimpleXMLIterator implements IteratorOf course, they would be wrong. The actual hierarchy is this:
SimpleXMLElement implements Traversable
SimpleXMLIterator extends SimpleXMLElement implements IteratorThe fact that SimpleXMLIterator extends SimpleXMLElement leaves me in a
tough spot, because it means SimpleXMLElement cannot be an
IteratorAggregate -- that would mean that SimpleXMLIterator implements both
IteratorAggregate and Iterator, which is not permissible.It seems that it's also not possible to remove the "extends" without a
non-trivial backwards-compatibility break, because apparently writing
simplexml_load_string($str, 'SimpleXMLIterator') is a thing, which requires
SimpleXMLIterator to extend SimpleXMLElement (and possibly is the reason
why this was done in the first place.)The only way out I see here is to lift the methods from SimpleXMLIterator
into SimpleXMLElement, make SimpleXMLElement implement Iterator itself, and
basically leave SimpleXMLIterator as a dummy extension of SimpleXMLElement.Does that sound "reasonable"? Or rather, is there something more reasonable
that can be done?Regards,
Nikita
Well, that did not work as intended...
OFFLIST
The “off list” command has an underscore in it: OFF_LIST.
;-)
Cheers,
Ben
Hi internals,
I'm currently trying to make sure that all internal Traversable classes
implement either Iterator or IteratorAggregate. This is a hard requirement
for userland classes, but internal classes can get away with implementing
only the internal get_iterator() mechanism. (
https://github.com/php/php-src/pull/5216)One problem I ran into along the way is the SimpleXMLIterator class. A
naive person might think that there is some sanity left in this world, and
the hierarchy for SXE/SXI looks like this:SimpleXMLElement implements IteratorAggregate // where SimpleXMLElement::getIterator() returns: SimpleXMLIterator implements Iterator
Of course, they would be wrong. The actual hierarchy is this:
SimpleXMLElement implements Traversable SimpleXMLIterator extends SimpleXMLElement implements Iterator
The fact that SimpleXMLIterator extends SimpleXMLElement leaves me in a
tough spot, because it means SimpleXMLElement cannot be an
IteratorAggregate -- that would mean that SimpleXMLIterator implements both
IteratorAggregate and Iterator, which is not permissible.It seems that it's also not possible to remove the "extends" without a
non-trivial backwards-compatibility break, because apparently writing
simplexml_load_string($str, 'SimpleXMLIterator') is a thing, which requires
SimpleXMLIterator to extend SimpleXMLElement (and possibly is the reason
why this was done in the first place.)The only way out I see here is to lift the methods from SimpleXMLIterator
into SimpleXMLElement, make SimpleXMLElement implement Iterator itself, and
basically leave SimpleXMLIterator as a dummy extension of SimpleXMLElement.Does that sound "reasonable"? Or rather, is there something more
reasonable that can be done?
I've put up https://github.com/php/php-src/pull/5234 to implement this...
Nikita