-
-
Save mvriel/3823010 to your computer and use it in GitHub Desktop.
| <?php | |
| /** | |
| * @template <T> The type of the individual elements | |
| */ | |
| class ArrayCollection implements IteratorAggregate | |
| { | |
| private $elements; | |
| /** | |
| * @param array<T> $elements | |
| */ | |
| public function __construct(array $elements) | |
| { | |
| $this->elements = $elements; | |
| } | |
| /** | |
| * @return Iterator<T> | |
| */ | |
| public function getIterator() | |
| { | |
| return new ArrayIterator($this->elements); | |
| } | |
| } | |
| // usage | |
| /** @type ArrayCollection<Foo> $col */ | |
| $col = new ArrayCollection(); | |
| foreach ($col as $elem) { | |
| // $elem is instance of Foo here | |
| } | |
| ?> | |
| <?php | |
| class ArrayCollection implements IteratorAggregate | |
| { | |
| private $elements; | |
| /** | |
| * @param mixed[] $elements | |
| */ | |
| public function __construct(array $elements) | |
| { | |
| $this->elements = $elements; | |
| } | |
| /** | |
| * @return ArrayIterator | |
| */ | |
| public function getIterator() | |
| { | |
| return new ArrayIterator($this->elements); | |
| } | |
| } | |
| // usage | |
| /** @type ArrayCollection|Foo[] $col */ | |
| $col = new ArrayCollection(); | |
| foreach ($col as $elem) { | |
| // $elem is instance of Foo here | |
| } | |
| ?> |
I see no problem with supporting:
@type array<object> a list of objects, we don't care about the type
@type array<string,object> a map of strings to objects
The @template proposals is not directly related to arrays and more about allowing to write generic classes in userland while still getting the best autocompletion/static analysis that is possible, and btw, you could have more than one @template annotation on your class if your class needs to fill in more holes (like key, and value in a map as in your \SplObjectStorage example).
I wanted to post here that I have not abandoned the discussion but I have been at PHPNW12 the past weekend and am still catching up. A proper response follows somewhere in the upcoming week
Could these ideas be successfully condensed into just this one syntax:
@type (class name or primitive type 'array')<(optional key type, ) (required member type) (description)
I have been thinking quite a bit about this proposal in the past time and to be honest, it is starting to grow on me. Though I am not so sure about the @template tag since that would only serve a purpose for a Collection object that only intends to be used with a specific set of values (that and I don't think the name @template is intuitive).
Some concerns that I still have:
- How to deal with generics where the value may be of several types? Use the or operator (|) as has been done so far?
- We should also support multi-dimensional notations
I think we sould keep the or operator for working with several types. But what do you mean by "multi-dimensional notations"?
Coming from a Java perspective, I would love some kind of Generics support in PHP and/or PHPDOC. 👍
Here is a sample that might make more sense regarding Johannes proposal:
Let's have a look at the SplObjectStorage class, that provides a map where keys can be objects. (http://www.php.net/manual/en/class.splobjectstorage.php)
I like Johannes proposal because I find it very powerful.
However, let's admit that 90% of the time, we are dealing with arrays, not ArrayCollection or SplObjectStorage, so we should be sure that the use of the @type annotation with the array is rock solid.
For this matter, one thing we do not capture is the difference between an indexed array and a hashmap. PHP does not make any difference between those 2 constructs, and yet, they are completely different and the documentation should tell the user whether the array is numerically indexed, or is a map.
A proposal would be to use 2 keys. For instance:
Now, this seems to be a bit of an overkill compared to the more simple proposal from Mike...
In an ideal world, we should also be able to write:
/** @type array<Object> An array of Objects (we don't know about the key) */But that would not suit well with the @template annotation....
So I'm a bit at a loss here... Any idea on how to make this both powerful and simple to use?