APIs should never be made more specific.
In fact, I consider it a bug that append(Myclass $value)
isn't a fatal error. I consider the The fatal error on your offsetSet()
as correct.
The reason for this is simple:
function f(ArrayObject $ao) {
$ao->append(5); //Error
}
$ao = new YourArrayObject();
With an append
with a type requirement, that will error. Nothing looks wrong with it though. You've effectively made the API more specific, and references to the base class are no longer able to be assumed to have the expected API.
What is basically comes down to is that if an API is made more specific, that sub class is no longer compatible with it's parent class.
This odd disparity can be seen with f
: it allows you to pass a Test
to it but will then fail on the $ao->append(5)
execution. If a echo 'hello world';
were above it, that would execute. I consider that incorrect behavior.
In a language like C++, Java or C#, this is where generics would come into play. In PHP, I'm afraid there's not a pretty solution to this. Run time checks would be nasty and error prone, and rolling your own class would completely obliterate the advantages of having ArrayObject as the base class. Unfortunately, the desire to have ArrayObject as the base class is also the problem here. It stores mixed types, so your subclasses must store mixed types as well.
You could perhaps implement that ArrayAccess interface in your own class and clearly mark that the class is only meant to be used with a certain type of object. That would still be a bit clumsy though, I fear.
Without generics, there's not a way to have a generalized homogeneous container without runtime instanceof-style checks. The only way would be to have a ClassAArrayObject, ClassBArrayObject, etc.