Jump to content
 







Main menu
   


Navigation  



Main page
Contents
Current events
Random article
About Wikipedia
Contact us
Donate
 




Contribute  



Help
Learn to edit
Community portal
Recent changes
Upload file
 








Search  

































Create account

Log in
 









Create account
 Log in
 




Pages for logged out editors learn more  



Contributions
Talk
 



















Contents

   



(Top)
 


1 Class invariants and inheritance  





2 Programming language support  



2.1  Assertions  





2.2  Native support  





2.3  Non-native support  







3 Examples  



3.1  Native support  



3.1.1  Ada  





3.1.2  D





3.1.3  Eiffel  







3.2  Non-native support  



3.2.1  C++  





3.2.2  Java  









4 References  














Class invariant






العربية
Español
Français
Italiano
Русский
 

Edit links
 









Article
Talk
 

















Read
Edit
View history
 








Tools
   


Actions  



Read
Edit
View history
 




General  



What links here
Related changes
Upload file
Special pages
Permanent link
Page information
Cite this page
Get shortened URL
Download QR code
Wikidata item
 




Print/export  



Download as PDF
Printable version
 
















Appearance
   

 






From Wikipedia, the free encyclopedia
 


Incomputer programming, specifically object-oriented programming, a class invariant (ortype invariant) 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. With concurrency, maintaining the invariant in methods typically requires a critical section to be established by locking the state using a mutex.

Anobject 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[edit]

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."[1]

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 (i.e., inheritance breaks encapsulation).[2]

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.

Programming language support[edit]

Assertions[edit]

Common programming languages like Python,[3] PHP,[4] JavaScript,[citation needed] 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.

Native support[edit]

The class invariant is an essential component of design by contract. So, programming languages that provide full native support for design by contract, such as Eiffel, Ada, and D, will also provide full support for class invariants.

Non-native support[edit]

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[edit]

Native support[edit]

Ada[edit]

The Ada programming language has native support for type invariants (as well as pre- and postconditions, subtype predicates, etc.). A type invariant may be given on a private type (for example to define a relationship between its abstract properties), or on its full definition (typically to help in verifying the correctness of the implementation of the type).[5] Here is an example of a type invariant given on the full definition of a private type used to represent a logical stack. The implementation uses an array, and the type invariant specifies certain properties of the implementation that enable proofs of safety. In this case, the invariant ensures that, for a stack of logical depth N, the first N elements of the array are valid values. The Default_Initial_Condition of the Stack type, by specifying an empty stack, ensures the initial truth of the invariant, and Push preserves the invariant. The truth of the invariant then enables Pop to rely on the fact that the top of the stack is a valid value, which is needed to prove Pop's postcondition. A more complex type invariant would enable the proof of full functional correctness, such as that Pop returns the value passed into a corresponding Push, but in this case we are merely trying to prove that Pop does not return an Invalid_Value.

generic
    type Item is private;
    Invalid_Value : in Item;
package Stacks is
    type Stack(Max_Depth : Positive) is private
        with Default_Initial_Condition => Is_Empty (Stack);

    function Is_Empty(S : in Stack) return Boolean;
    function Is_Full(S : in Stack) return Boolean;

    procedure Push(S : in out Stack; I : in Item)
        with Pre  => not Is_Full(S) and then I /= Invalid_Value,
             Post => not Is_Empty(S);
    procedure Pop(S : in out Stack; I : out Item)
        with Pre  => not Is_Empty(S),
             Post => not Is_Full(S) and then I /= Invalid_Value;
private
    type Item_Array is array (Positive range <>) of Item;

    type Stack(Max_Depth : Positive) is record
        Length : Natural := 0;
        Data : Item_Array (1 .. Max_Depth) := (others => Invalid_Value);
    end record
        with Type_Invariant => Length <= Max_Depth and then
          (for all J in 1 .. Length => Data (J) /= Invalid_Value);

    function Is_Empty(S : in Stack) return Boolean
        is (S.Length = 0);
    function Is_Full(S : in Stack) return Boolean
        is (S.Length = S.Max_Depth);
end Stacks;

D[edit]

D programming language has native support of class invariants, as well as other contract programming techniques. Here is an example from the official documentation.[6]

class Date {
  int day;
  int hour;

  invariant() {
    assert(day >= 1 && day <= 31);
    assert(hour >= 0 && hour <= 23);
  }
}

Eiffel[edit]

InEiffel, the class invariant appears at the end of the class following the keyword invariant.

class
 DATE

create
 make

feature {NONE} -- Initialization

 make (a_day: INTEGER; a_hour: INTEGER)
   -- 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 (a_day: INTEGER)
   -- 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 (a_hour: INTEGER)
   -- 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[edit]

C++[edit]

The Loki (C++) 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:

#include <loki/Checker.h>  // Needed to check class invariants.

#include <Degrees.hpp>

class GeoPoint {
 public:
  GeoPoint(Degrees latitude, Degrees longitude);

  /// Move function will move location of GeoPoint.
  void Move(Degrees latitude_change, Degrees longitude_change) {
    // The checker object calls IsValid at function entry and exit to prove this
    // GeoPoint object is valid. The checker also guarantees GeoPoint::Move
    // function will never throw.
    CheckFor::CheckForNoThrow checker(this, &IsValid);

    latitude_ += latitude_change;
    if (latitude_ >= 90.0) latitude_ = 90.0;
    if (latitude_ <= -90.0) latitude_ = -90.0;

    longitude_ += longitude_change;
    while (longitude_ >= 180.0) longitude_ -= 360.0;
    while (longitude_ <= -180.0) longitude_ += 360.0;
  }

 private:
  /** @note CheckFor performs validity checking in many functions to determine
   if the code violated any invariants, if any content changed, or if the
   function threw an exception.
   */
  using CheckFor = ::Loki::CheckFor<const GeoPoint>;

  /// This function checks all object invariants.
  bool IsValid() const {
    assert(this != nullptr);
    assert(latitude_ >= -90.0);
    assert(latitude_ <= 90.0);
    assert(longitude_ >= -180.0);
    assert(longitude_ <= 180.0);
    return true;
  }

  Degrees latitude_;   ///< Degrees from equator. Positive is north, negative is
                       ///< south.
  Degrees longitude_;  ///< Degrees from Prime Meridian. Positive is east,
                       ///< negative is west.
}

Java[edit]

This is an example of a class invariant in the Java programming language with Java Modeling Language. The invariant must hold to be true after the constructor is finished and at the entry and exit of all public member functions. Public member functions should define precondition and postcondition to help ensure the class invariant.

public class Date {
    int /*@spec_public@*/ day;
    int /*@spec_public@*/ hour;

    /*@invariant day >= 1 && day <= 31; @*/ //class invariant
    /*@invariant hour >= 0 && hour <= 23; @*/ //class invariant

    /*@
    @requires d >= 1 && d <= 31;
    @requires h >= 0 && h <= 23;
    @*/
    public Date(int d, int h) { // constructor
        day = d;
        hour = h;
    }

    /*@
    @requires d >= 1 && d <= 31;
    @ensures day == d;
    @*/
    public void setDay(int d) {
        day = d;
    }

    /*@
    @requires h >= 0 && h <= 23;
    @ensures hour == h;
    @*/
    public void setHour(int h) {
        hour = h;
    }
}

References[edit]

  1. ^ Meyer, Bertrand. Object-Oriented Software Construction, second edition, Prentice Hall, 1997, p. 570.
  • ^ E. Gamma, R. Helm, R. Johnson, and J. Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley, Reading, Massachusetts, 1995., p. 20.
  • ^ Official Python Docs, assert statement
  • ^ "PHP assert function". Archived from the original on 2001-03-21.
  • ^ "Ada Reference Manual 7.3.2 Type Invariants". ada-auth.org. Retrieved 2022-11-27.
  • ^ "Contract Programming - D Programming Language". dlang.org. Retrieved 2020-10-29.

  • Retrieved from "https://en.wikipedia.org/w/index.php?title=Class_invariant&oldid=1231958078"

    Category: 
    Class (computer programming)
    Hidden categories: 
    Articles with short description
    Short description matches Wikidata
    Articles needing additional references from August 2010
    All articles needing additional references
    All articles with unsourced statements
    Articles with unsourced statements from February 2021
     



    This page was last edited on 1 July 2024, at 05:12 (UTC).

    Text is available under the Creative Commons Attribution-ShareAlike License 4.0; additional terms may apply. By using this site, you agree to the Terms of Use and Privacy Policy. Wikipedia® is a registered trademark of the Wikimedia Foundation, Inc., a non-profit organization.



    Privacy policy

    About Wikipedia

    Disclaimers

    Contact Wikipedia

    Code of Conduct

    Developers

    Statistics

    Cookie statement

    Mobile view



    Wikimedia Foundation
    Powered by MediaWiki