Consider the following class Foo.
class Foo
{
private int x = 0
private int y = 0
invariant y = 2× x
public void f()
{
x += 1
y += 2
}
public void g()
{
x *= 3
y *= 3
}
}
It has an invariant — you all know what an invariant is, of cousre — anyway, this invariant
says that y is always twice x. The initial values, x = y = 0, respect the invariant. Both
functions, f and g, maintain the invariant. Everything’s fine.
Now let’s give it a variable b and call b’s function h. Note that this does not change the (so-
called) interface of Foo, because the new variable is private and the call is an implementation
secret of Foo.f .
class Foo
{
private int x = 0
private int y = 0
private Bar b
invariant y = 2 * x
public void f()
{
x += 1
b.h()
y += 2
}
public void g()
{
x *= 3
y *= 3
}
}
Now look at class Bar. It’s method h calls Foo’s function g.
class Bar
{
private Foo f
public void h()
{
f.g();
}
}
This has unexpected consequences for Foo. Think of the interface as being the top of the
box. The damage is done by the thread of control coming out of the bottom of the box —
nothing to do with the “interface”.Here is the sequence of assignments that take place and
the resulting values:
x = 0 0
y = 0 0
x += 1 1
x *= 3 3
y *= 3 0
y += 2 2
The invariant now says 2 = 2 ×3. Oops! The call b.h() in class Foo is an important part of
its behaviour — and therefore must be considered as part of its interface.
Note how Foo has lost control of its “private” internals. As a technical aside, note also that
if Foo was a monitor allowing only one method to be executed at a time, this program would
deadlock.
I’ve presented this as an example of the meaning of interface. But you should note that it
is really quite a serious problem: objects have no control over their private data. This is a consequence of the fact that objects can invoke functions in other objects.