The underlying assumption is that the `.items` slot is a list
(or an expression), and that slot is the only slot for which
it's order and length are meaningful (i.e. there is no other list
or vector of same length as `.items` in a different slot that is
supposed to map to `.items`). This last assumption allows us
to implement the subsetting operators in a meaningful manner.
The validity method will run validObject
on the first, last, and
middle items (if an even number of items, then the middle closer to the
first) assuming they are S4 objects. We don't run on every object to avoid
potentially expensive computation on all objects.