Open In App

What is class Invariant

Last Updated : 22 Jun, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Overview :
An invariant in Object-Oriented programming refers to some set of conditions or assertions that need to hold throughout the life of an object of a class. These assertions need to hold from the time the constructor is called for an object, at the end of each member (mutator) method call to the end of the destructor call. These conditions verify that an object’s behavior is justified during its lifetime and that the object maintains its well-defined state as intended. The invariant, however, need not hold true during the execution of a mutator method but must hold true at the end of it.

Example :
Creating a snake game –
Let’s say we were creating a snake game and our snake had the ability to teleport itself a few blocks in some direction. Let us also define our invariant that our snake’s head should not cross the playground bounds. Now, if we ensure that our invariant holds at the end of the function where we implement our teleportation ability, we are good. Otherwise, our assertions will fail, and we will find out that there probably is a bug in our code.

Code Implementation in C++ :
As a good programming practice, an invariant private member method is created whose duty is to check that all necessary conditions stay uncompromising and that all methods can make reasonable assumptions about the state of the object. We call this invariant member method at the end of constructors and every mutator method.

Code –

C++




#include <bits/stdc++.h>
using namespace std;
  
// self defined struct to 
// hold the position of snake
struct Pos
{
    int x;
    int y;
    Pos(int _x = 0, int _y = 0)
    {
        this->x = _x;
        this->y = _y;
    }
};
  
class Snake
{
private:
    int play_width; // right bound
    int play_height; // height bound
    Pos loc; // position of snake's head
    void Invariant()
    {
        assert(loc.x >= 0 && loc.x <= play_width);
        assert(loc.y >= 0 && loc.y <= play_height);
    }
public:
    // initialise the snake object with _width ans _height bounds
    // ans posx, posy current position
    Snake(int _width, int _height, Pos _p)
    {
        this->play_width = _width;
        this->play_height = _height;
        this->loc.x = _p.x;
        this->loc.y = _p.y;
        // call the invariant to ensure the object
        // was constructed correctly
        Invariant();
    }
  
    // teleport and add inc.x units to current X coordinate
    // ans inc.y units to Y coordinate of snake 
    void TeleportAhead(Pos inc)  
    {
        loc.x += inc.x;
        loc.y += inc.y;
        //ensure that our snake wasn't 
        // teleported out of play bounds
        Invariant();
    }
  
    // return current position
    // calling invariant is unnecessary
    // because this is an accessor method
    Pos GetLoc()
    {
        return loc;
    }
};
  
  
  
int main()
{
    Snake snek(30, 20, Pos(5, 5));
  
    // will throw assert error because
    // our snake is teleported out of bound
    snek.TeleportAhead(Pos(20, 20));
  
    // will also fail Invariant() assertion
    // because the snake is being spawned out
    // of bounds
    Snake snek2(10, 10, Pos(12, 8));
    return 0;
}




Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads