Hello, internals!

Recently I was implementing some collections and realized that I cannot use
`ArrayAccess` for immutable collections without throwing
`BadMethodCallException` in `offsetSet` and `offsetUnset`. I also cannot
have an `interface ReadonlyCollection extends ArrayAccess`, because
`offsetSet` and `offsetUnset` are mutators and have `TValue` in a
contravariant position.

Here's the idea: let's extract `ArrayAccess::offsetExists` and
`ArrayAccess::offsetGet` methods into a separate `ArrayAccessRead`
interface (name can be different) and allow read operations `$exists =
isset($object['key'])` and `$value = $object['key']` for objects of classes
that implement this interface. `ArrayAccess` will then extend
`ArrayAccessRead` and add the remaining 2 methods. Looks like this change
should not break backward compatibility.

```
interface ArrayAccessRead
{
    public function offsetExists(mixed $offset): bool;
    public function offsetGet(mixed $offset): mixed;
}

interface ArrayAccess extends ArrayAccessRead
{
    public function offsetSet(mixed $offset, mixed $value): void;
    public function offsetUnset(mixed $offset): void;
}

// then interfaces of the doctrine/collections package might look like this:

namespace Doctrine\Common\Collections;

interface ReadableCollection extends Countable, IteratorAggregate,
ArrayAccessRead {}
interface Collection extends ReadableCollection, ArrayAccess {}
```
-- 
Regards, Valentin Udaltsov

Reply via email to