这个问题有点宽泛和概念化。
我有一堂有各种方法的课。让我们称它们为A
and B
。如何确保将来使用此类的其他开发人员在第一次调用方法 A 之前不会调用方法 B 至少一次?
我在 C++ 中执行此操作,但一般而言,执行此操作的最佳方法是什么?我有一些天真的想法,例如使用布尔变量,但我也想听听其他一些想法。
保证这一点的一种方法?让方法 B 负责调用方法 A 一次。
其他任何东西都是脆弱的 API。
有一个布尔变量来确定是否A
已被调用。然后,当有人尝试在B
未设置此布尔变量的情况下调用时,抛出 IllegalStateException。
或者您可以B
简单地调用A
,因为它似乎无法在不A
首先调用的情况下执行。
否则,由于这两种方法都是公开的,因此实际上没有其他方法可以强制执行此操作。
使用布尔值是一个好的开始,并且投入访问工作正常。
然而,有时能够在编译时强制执行这一点很好。在这种情况下,您唯一真正的选择是使用一些技巧。
仅在您的类中公开 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() 的基类的受保护继承来实现类似的目的。
一种方法是稍微不同地重新设计您的课程。考虑一个在使用前需要初始化的简单数据库类。我是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");
保证它的一种方法A
是在类的构造函数中完成。如果构造函数失败(抛出),那么其他开发人员就没有什么可以做的错误B
了。如果构造函数成功,则A
至少完成一次,B
有效的操作也是如此。
我会将方法“A”作为构造函数来初始化对象。这必须调用一次才能使用由编译器强制执行的对象。稍后您可以在必须调用构造函数的情况下调用方法“B”。