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

Cem*_*mre 5 c++ java methods call

这个问题有点宽泛和概念性.

我有一个有各种方法的课.让我们把它们AB.我怎样才能确保将来使用此类的其他开发人员在首次调用方法A之前不会调用方法B?

我在C++中这样做,但一般来说,执行此操作的最佳方法是什么?我有一些天真的想法,比如使用布尔变量,但我也希望听到其他一些想法.

Mit*_*eat 10

一种方法来保证这一点?让方法B负责调用方法A一次.

其他任何东西都是脆弱的API.


Joã*_*lva 5

有一个布尔变量来确定是否A已被调用。然后,当有人试图在B没有设置这个布尔变量的情况下调用时,抛出一个 IllegalStateException。

或者您可以B简单地调用,A因为它似乎无法在不A首先被调用的情况下执行。

否则,由于这两种方法都是公开的,因此真的没有其他方法可以强制执行此操作。


Mic*_*son 5

使用布尔值是一个良好的开端,抛出访问可以正常工作.

但是,有时能够在编译时强制执行此功能.在这种情况下,你唯一真正的选择是使用一些技巧.

只在您的类中公开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.
}
Run Code Online (Sandbox Code Playgroud)

您还可以使用实现(或提供虚拟)B()的基类的受保护继承来实现类似的功能.


jef*_*eff 5

一种方法是重新设计你的课程有点不同.考虑一个简单的数据库类,需要在使用之前进行初始化.我是一个Java人,所以......

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

所以我需要先调用init.我可以创建一个DatabaseFactory来执行初始化并返回实际的数据库对象.我们可以隐藏构造函数,这样只有DatabaseFactory才能创建数据库(在Java中是一个嵌套类,在C++中可能是朋友类?).

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

   public class Database {
     private Database() {}
     public List<Object> runQuery(String sql) // ...
   }
}
Run Code Online (Sandbox Code Playgroud)

所以现在我必须通过工厂来获取底层对象.

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");
Run Code Online (Sandbox Code Playgroud)