5

这个问题有点宽泛和概念化。

我有一堂有各种方法的课。让我们称它们为Aand B。如何确保将来使用此类的其他开发人员在第一次调用方法 A 之前不会调用方法 B 至少一次?

我在 C++ 中执行此操作,但一般而言,执行此操作的最佳方法是什么?我有一些天真的想法,例如使用布尔变量,但我也想听听其他一些想法。

4

6 回答 6

10

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

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

于 2012-08-26T02:13:53.767 回答
5

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

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

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

于 2012-08-26T02:14:33.167 回答
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.
}

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

于 2012-08-26T02:21:05.733 回答
5

一种方法是稍微不同地重新设计您的课程。考虑一个在使用前需要初始化的简单数据库类。我是Java人,所以...

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

所以我需要先调用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) // ...
   }
}

所以现在我必须通过工厂才能到达底层对象。

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");
于 2012-08-26T02:32:37.700 回答
2

保证它的一种方法A是在类的构造函数中完成。如果构造函数失败(抛出),那么其他开发人员就没有什么可以做的错误B了。如果构造函数成功,则A至少完成一次,B有效的操作也是如此。

于 2012-08-26T02:45:01.030 回答
2

我会将方法“A”作为构造函数来初始化对象。这必须调用一次才能使用由编译器强制执行的对象。稍后您可以在必须调用构造函数的情况下调用方法“B”。

于 2012-08-26T07:00:18.173 回答