The difference is between What something is, and How something behaves.
A lot of languages try to conflate the two together, but they are quite distinct things.
If How is What, and What is How...
If everything inherits from object
then some benefits occur like: any variable of object can hold any value ever. But that is also the rub, everything must behave (the how) like an object
, and look like (the what) an object
.
But:
- What if your object does not have a meaningful definition of equality?
- What if it does not have a meaningful hash?
- What if your object cannot be cloned, but objects can be?
Either the object
type becomes essentially useless - due to object providing no commonality across all the possible instances. Or there will exist objects that have a broken/shoe-horned/absurd definition of some presumed universal property found on object
which provies almost universal behaviour except for a number of gotchas.
If What is not bound up with How
Alternately you can keep the What and the How separate. Then several different Types (with nothing in common at all the what) can all behave in the same way as seen from the collaborator the how. In this sense the idea of an Iterator
is not a specific what, but a how. Specifically How do you interact with a thing when you do not yet know What you are interacting with.
Java (and similar) allow approaches to this by using interfaces. An interface in this regard describes the means of communication, and implicitly a protocol of communication and action that is followed. Any What which declares itself to be of a given How, states that it supports the relevant communication and action outlined by the protocol. This allows any collaborator to rely on the How and not get bogged down by specifying exactly which What's can be used.
C++ (and similar) allow approaches to this by duck typing. A template does not care if the collaborating type declares that it follows a behaviour, just that within a given compilation context, that the object can be interacted with in a particular manner. This allows C++ pointers, and Objects over-riding specific operators to be used by the same code. Because they meet the check-list to be considered equivalent.
- supports *a, a->, ++a, and a++ -> input/forward iterator
- supports *a, a->, ++a, a++, --a, and a-- -> bidirectional iterator
The underlying type does not even have to be iterating a container, it could be any what. Additionally it allows some collaborators to be even more generic, imagine a function only needs a++
, an iterator can satisfy that, so can a pointer, so can an integer, so could any object implementing operator++
.
Under and Over Specification
The problem with both approaches is under and over specification.
Using an interface requires the object to declare it supports a given behaviour, which also means that the creator must imbue that from the beginning. This causes some What's to not make the cut, as they did not declare it. It also means that ever What has a common ancestor, the interface representing the How. This does circle back to the initial problem of object
. This causes collaborators to over-specify their requirements, while simultaneously causing some objects to be either unusable due to a lack of declaration, or be hidden gotchas as an expected behaviour is poorly defined.
Using a template requires that the collaborator works with a completely unknown What, and through its interactions it defines a How. To some extent this makes writing collaborators harder, as it must analyse the What for its communication primitives (functions/fields/etc) while avoiding compilation errors, or at least point out how a given What does not match its requirements for the How. This allows the collaborator to require the absolute minimum from any given What, allowing the broadest range of what's to be used. Unfortunately this has the downside of allowing nonsensical uses of objects which technical provide the communication primitives for a given How, but do not follow the implied protocol allowing all sorts of bad things to occur.
Iterators
In this case an Iterator
is a How it is shorthand for a description of interaction. Anything that matches that description is by definition an Iterator
. Knowing How allows us to write general algorithms and have a short list of 'How's given a specific What' that need to be provided in order to make the algorithm work. That list are the function/properties/etc, their implementation takes into account the specific What that is being dealt with by the algorithm.