简体   繁体   English

防止在另一个方法之前调用方法

[英]Preventing a method being called before another one

This is question is a bit broad and conceptual. 这个问题有点宽泛和概念性。

I have a class with various methods. 我有一个有各种方法的课。 Let's call them A and B . 我们称他们为AB How can I make sure that other developers working with this class in the future will not call method B before first calling method A at least once ? 我怎样才能确保将来使用此类的其他开发人员在首次调用方法A之前不会调用方法B?

I am doing this in C++ but in general what's the best way to enforce this ? 我在C ++中这样做,但一般来说,执行此操作的最佳方法是什么? I have naive some ideas such as using a boolean variable but I would like to hear some other thoughts as well. 我有一些天真的想法,比如使用布尔变量,但我也希望听到其他一些想法。

One way to guarantee this? 一种方法来保证这一点? Make it the responsibility of method B to call method A once. 让方法B负责调用方法A一次。

Anything else is a fragile API. 其他任何东西都是脆弱的API。

Using a boolean is a good start, and throwing on access works OK. 使用布尔值是一个良好的开端,抛出访问可以正常工作。

However sometimes its nice to be able to enforce this at compile-time. 但是,有时能够在编译时强制执行此功能。 In that case your only real option is to use some tricks. 在这种情况下,你唯一真正的选择是使用一些技巧。

Only expose A in your class, make it return a proxy containing B. 只在您的类中公开A,使其返回包含B的代理。

class MyClass {
  public:

    struct BProxy {
      public:
        MyClass * root;
        void B() { root->B(); }
      protected:
        BProxy( MyClass * self ) : root(self) {}; // Disable construction
        friend class MyClass; //So that MyClass can construct it
    };

    BProxy A() { ... return BProxy(this); }
    friend class BProxy; // So that BProxy can call B()
  protected
   void B() { ... }
};

int main() {
   MyClass m;
   BProxy bp = m.A(); 
   // m.B(); can't do this as it's private - will fail at compile time.
   bp.B(); // Can do this as we've got the proxy from our previous call to A.
}

You can also achieve something similar using protected inheritance from a baseclass implementing (or providing a virtual) B(). 您还可以使用实现(或提供虚拟)B()的基类的受保护继承来实现类似的功能。

One way is to redesign your class a little differently. 一种方法是重新设计你的课程有点不同。 Consider a simple database class that needs to be initialized before being used. 考虑一个简单的数据库类,需要在使用之前进行初始化。 I'm a Java guy, so... 我是一个Java人,所以......

public class Database {
  public void init(String username, String password) // must call this first!
  public List<Object> runQuery(String sql) // ...
}

So I need to call init first. 所以我需要先调用init。 I can make a DatabaseFactory that does the initialization and returns the actual database object. 我可以创建一个DatabaseFactory来执行初始化并返回实际的数据库对象。 We can hide the constructor so that only a DatabaseFactory can create a Database (in Java a nested class, in C++ a friend class maybe?). 我们可以隐藏构造函数,这样只有DatabaseFactory才能创建数据库(在Java中是一个嵌套类,在C ++中可能是朋友类?)。

public class DatabaseFactory {
   public Database init(String username, String password) // ...

   public class Database {
     private Database() {}
     public List<Object> runQuery(String sql) // ...
   }
}

So now I must go through the Factory to get to the underlying object. 所以现在我必须通过工厂来获取底层对象。

DatabaseFactory factory = new DatabaseFactory();
Database database = factory.init("username", "password"); // first init (call method A)
// now I can use database (or B in your case)
database.runQuery("select * from table");

Have a boolean variable that determines if A has been called. 有一个布尔变量,用于确定是否已调用A Then, when someone tries to invoke B without this boolean variable being set, throw an IllegalStateException. 然后,当有人试图在没有设置此布尔变量的情况下调用B ,抛出IllegalStateException。

Or you could have B simply call A since it seems that it cannot execute without A being called first anyways. 或者你可以让B简单地调用A因为它似乎无法在没有A被调用的情况下执行。

Otherwise, and since both methods are public, there's really no other way to enforce this. 否则,由于这两种方法都是公开的,因此实际上没有其他方法可以强制执行。

One way to guarantee it is that A is done in the constructor of the class. 保证它的一种方法是A在类的构造函数中完成。 If the constructor fails (throws) then the other developers do not have anything with what to do that erroneous B with. 如果构造函数失败(抛出),那么其他开发人员没有任何关于该错误B的操作。 If the constructor succeeds then A is done at least once and so B is valid operation to do. 如果构造函数成功,则A至少完成一次,因此B是有效的操作。

I would make method "A" the constructor to initialise the object. 我会使方法“A”构造函数初始化对象。 This has to called once to use the object, enforced by the compiler. 这必须调用一次使用由编译器强制执行的对象。 Later you can call a method "B" in the knowledge that a constructor must have been called. 之后,您可以在必须调用构造函数的知识中调用方法“B”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM