It is a common belief that behaviour conformance is not statically
checkable. Let's demonstrate the contrary on a detail of the hopefully
familiar example of the dining philosophers ([Hoare85]):
Philosophers are sitting around a table, eating spaghetti. A
philosopher is defined by his ability to take a pair of forks, eat,
and place the forks back on the table (there is just as many forks as
there are philosophers). The detail, we choose to focus on, is how to
statically ensure that users of the philosopher type cannot attempt to
have them pick up forks twice in a row, or put them back on the table
before they have first taken them. A simple answer using C++ concepts
is to offer one only public member function, "eat", in a philosopher
abstract class, and define it in this class to call in sequence three
virtual protected members, "take_forks", "eat_" and "put_forks".
This simple technique shows a (trivial) behaviour specification:
the key point here is that the code, defined in the abstract class, is
itself part of the interface, not of the yet undefined implementation
of the philosophers. This technique can be extended to support
protocols of significant complexity by resorting to dedicated
interfaces (e.g. in C++, through friendship):
Let's now suppose that instead of the former requirement, we would
have had to consider the situation from the point of view of fork
pairs (to keep it simpler): two members, "take" and "put" and the same
constraints. We would have made these virtual members protected, and
designed an abstract "eater" class as a "friend". This one would have
only differed from the formerly sketched "philosopher" in that it
would have delegated the reclaiming and disposing of the forks to
external resources. This would have constrained new "philosophers" to
specialize our "eater" class, making this one, in fact, the
"fork_pair"'s interface.
We acknowledge that we are not yet even on the way to solve
Hoare's initial puzzle. This is however sufficient for our purpose.
This kind of design is such uncommon that e.g. [BR95] sacrifices it in
C++, [Vinoski93] in IDL, in favour of a weaker signature
compatibility. Signature is the term coined by [BR95]. It is
extrapolated from the concept of function signature: the name of the
function, decorated with the type of its input parameters for linking
purposes. This is a key element in the way static typing has
traditionally been implemented e.g. in C. A class's signature is the
set of all the signatures of its public member functions. Vinoski uses
the term behaviour for a very similar concept in IDL, stressing with
this choice the fact that IDL interfaces do not describe any data. We
reserve behaviour (following [WZ88]) for the service expected by a
client from a type, expressed at least conceptually through
relationships between the pre- and post-conditions of the class
members. From a classical example, a square and a cowboy may have the
same signature, if they have only one member, draw. They have yet
different behaviours.