In computer programming, specifically object-oriented programming, a classinvariant is an invariant used for constraining objects of a class. Methods of the class should preserve the invariant. The class invariant constrains the state stored in the object. Class invariants are established during construction and constantly maintained between calls to public methods. Code within functions may break invariants as long as the invariants are restored before a public function ends. An object invariant, or representation invariant, is a computer programming construct consisting of a set of invariant properties that remain uncompromised regardless of the state of the object. This ensures that the object will always meet predefined conditions, and that methods may, therefore, always reference the object without the risk of making inaccurate presumptions. Defining class invariants can help programmers and testers to catch more bugs during software testing.
Class invariants and inheritance
The useful effect of class invariants in object-oriented software is enhanced in the presence of inheritance. Class invariants are inherited, that is, "the invariants of all the parents of a class apply to the class itself." Inheritance can allow descendant classes to alter implementation data of parent classes, so it would be possible for a descendant class to change the state of instances in a way that made them invalid from the viewpoint of the parent class. The concern for this type of misbehaving descendant is one reason object-oriented software designers give for favoring composition over inheritance. However, because class invariants are inherited, the class invariant for any particular class consists of any invariant assertions coded immediately on that class in conjunction with all the invariant clauses inherited from the class's parents. This means that even though descendant classes may have access to the implementation data of their parents, the class invariant can prevent them from manipulating those data in any way that produces an invalid instance at runtime.
Common programming languages like Python, JavaScript, C++ and Java support assertions by default, which can be used to define class invariants. A common pattern to implement invariants in classes is for the constructor of the class to throw an exception if the invariant is not satisfied. Since methods preserve the invariants, they can assume the validity of the invariant and need not explicitly check for it.
For C++, the Loki Library provides a framework for checking class invariants, static data invariants, and exception safety. For Java, there is a more powerful tool called Java Modeling Language that provides a more robust way of defining class invariants.
Examples
Native support
D
programming language has native support of class invariants, as well as other contract programming techniques. Here is an example from the official documentation. class Date
Eiffel
In Eiffel, the class invariant appears at the end of the class following the keyword invariant. class DATE create make feature -- Initialization make -- Initialize `Current' with `a_day' and `a_hour'. require valid_day: a_day >= 1 and a_day <= 31 valid_hour: a_hour >= 0 and a_hour <= 23 do day := a_day hour := a_hour ensure day_set: day = a_day hour_set: hour = a_hour end feature -- Access day: INTEGER -- Day of month for `Current' hour: INTEGER -- Hour of day for `Current' feature -- Element change set_day -- Set `day' to `a_day' require valid_argument: a_day >= 1 and a_day <= 31 do day := a_day ensure day_set: day = a_day end set_hour -- Set `hour' to `a_hour' require valid_argument: a_hour >= 0 and a_hour <= 23 do hour := a_hour ensure hour_set: hour = a_hour end invariant valid_day: day >= 1 and day <= 31 valid_hour: hour >= 0 and hour <= 23 end
Non-native support
C++
The Loki library provides a framework written by Richard Sposato for checking class invariants, static data invariants, and exception safety level. This is an example of how class can use Loki::Checker to verify invariants remain true after an object changes. The example uses a geopoint object to store a location on Earth as a coordinate of latitude and longitude. The geopoint invariants are: