【问题标题】:Preventing a method being called before another one防止一个方法在另一个方法之前被调用
【发布时间】:2012-08-21 01:32:25
【问题描述】:

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

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

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

【问题讨论】:

标签: java c++ methods call


【解决方案1】:

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

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

【讨论】:

  • 这是一个好主意(+1),请注意,这样做的一个缺点是调用 A 所需的所有信息都必须传递给 B - 这可能很糟糕。 (想象一下需要将所有数据库连接数据传递给每个查询......)
  • 另外,“唯一的方式”有点强 IMO。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    使用布尔值是一个好的开始,并且抛出访问也可以。

    但有时能够在编译时强制执行这一点很不错。在这种情况下,您唯一真正的选择是使用一些技巧。

    只在你的类中公开 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() 的基类的受保护继承来实现类似的功能。

    【讨论】:

      【解决方案4】:

      一种方法是稍微不同地重新设计您的课程。考虑一个在使用前需要初始化的简单数据库类。我是 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");
      

      【讨论】:

        【解决方案5】:

        保证它的一种方法是A 在类的构造函数中完成。如果构造函数失败(抛出),那么其他开发人员将不知道该怎么做那个错误的B。如果构造函数成功,则 A 至少执行一次,因此 B 是有效的操作。

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-04-01
            • 2012-03-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多