[英]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
. 我们称他们为A
和B
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.