What is class Invariant
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; } |
Please Login to comment...