📜  什么是类不变式

📅  最后修改于: 2022-05-13 01:57:14.627000             🧑  作者: Mango

什么是类不变式

概述 :
一个不变量 在面向对象编程中是指在类的对象的整个生命周期中需要保持的一些条件或断言集。这些断言需要从为对象调用构造函数的时间开始,从每个成员(mutator)方法调用结束到析构函数调用结束。这些条件验证对象的行为在其生命周期内是合理的,并且对象按预期保持其明确定义的状态。然而,不变量不需要在执行 mutator 方法期间保持为真,而必须在它结束时保持为真。

例子 :
创建蛇游戏——
假设我们正在创建一个蛇游戏,我们的蛇能够将自己传送到某个方向几个街区。让我们也定义我们的不变量,即我们的蛇头不应该越过操场边界。现在,如果我们确保我们的不变量在我们实现传送能力的函数的末尾保持不变,我们就很好了。否则,我们的断言将失败,我们会发现我们的代码中可能存在错误。

C++ 代码实现:
作为一种良好的编程实践,创建了一个不变的私有成员方法,其职责是检查所有必要条件是否保持不妥协,并且所有方法都可以对对象的状态做出合理的假设。我们在构造函数和每个 mutator 方法的末尾调用这个不变的成员方法。

代码 -

C++
#include 
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;
}