Invariants

Sather - A Language Tutorial
Prev | Chapter 11. Safety Features | Next

# 11.4. Invariants

A class invariant is a condition that should never be violated in any object, after it has been created. Invariants have not proven to be as widely used as pre- and post- conditions, which are quite ubiquitous in Sather code.

## 11.4.1. The invariant routine

If a routine with the signature '`invariant:BOOL`', appears in a class, it defines a class invariant. It is a fatal error for it to evaluate to `false` after any public method of the class returns, yields, or quits.

Consider a class with a list (we use the library class A_LIST) whose size must always be at least 1. Such a situtation could arise if the array usually contains the same sort of elements and we want to use the first element of the array as a prototypical element)

    class PROTO_LIST is
       private attr l:A_LIST{FOO};

       create(first_elt:FOO):SAME is
          res ::= new;
          res.l := #;
          res.l.append(first_elt);
          return res;
       end;

       invariant:BOOL is
          return l.size > 0
       end;

       delete_last:FOO is
          return l.delete_elt(l.size-1);
       end;
    end;

If the 'delete_last' operation is called on the last element, then the assertion will be violated and an error will result.

    proto:FOO := #;   -- Some FOO object
    a:PROTO_LIST := #(FOO);
    last:FOO := a.delete_last;
       -- At runtime, an invariant violation will occur
       -- for trying to remove the last element.

The invariant is checked at the end of every public method. However, the invariant is not checked after a private routine. If we have the additional routines

    delete_and_add is
       res ::= internal_delete_last;
       l.append(res);
       return res;
    end;

    private internal_delete_last:FOO is
       return l.delete_elt(l.size-1);
    end;

Now we can call 'delete_and_add'

    proto:FOO := #;
    a:PROTO_LIST := #(FOO);
    last:FOO := a.delete_and_add;  -- does not violate the class invariant

The private call to 'internal_delete_last' does violate the invariant, but it is not checked, since it is a private routine.

Prev | Home | Next
Assertions | Up | Built-in classes