2012-08-26 3 views
5

이것은 다소 광범위하고 개념적입니다.다른 하나보다 먼저 호출되는 메소드 방지하기

나는 다양한 방법으로 수업을 진행합니다. AB이라고합시다. 앞으로이 클래스를 사용하는 다른 개발자가 A 메서드를 적어도 한 번 호출하기 전에 B 메서드를 호출하지 않도록하려면 어떻게해야합니까?

나는 이것을 C++에서하고 있지만, 일반적으로 이것을 강제하는 가장 좋은 방법은 무엇입니까? 나는 부울 변수를 사용하는 것과 같은 순진한 아이디어를 가지고 있지만 다른 생각을 듣고 싶습니다.

+0

당신은 실제로 명령을 시행 할 수 없습니다 (이미 언급 된 해결책이 있습니다). 템플릿 패턴으로 다시 디자인하고이 특별한 필요성을 피할 수 있습니다. http://en.wikipedia.org/wiki/Template_method_pattern – Jayan

답변

10

이것을 보장하는 한 가지 방법은 무엇입니까? 메서드 A를 한 번 호출하면 메서드 B가 책임집니다.

다른 모든 API는 취약합니다.

+1

이것은 좋은 생각입니다 (+1). 단점은 A를 호출하는 데 필요한 모든 정보가 B에 전달되어야한다는 것입니다. 슬프다. (모든 DB 연결 데이터를 모든 쿼리에 전달할 필요가 있다고 상상해보십시오 ...) –

+0

또한 "유일한 방법"은 약간 강한 IMO입니다. –

+0

좋습니다, 좋은 지적입니다. –

4

A이 호출되었는지를 결정하는 부울 변수가 있습니다. 그런 다음이 부울 변수를 설정하지 않고 누군가 B을 호출하려고하면 IllegalStateException을 발생시킵니다.

BA을 호출 할 수 있습니다. A이 먼저 호출되지 않으면 실행할 수없는 것 같습니다.

두 가지 방법이 모두 공개되었으므로이를 적용 할 방법이 없습니다.

5

부울을 사용하는 것이 좋은 시작이며 액세스가 성공하는 것은 정상입니다.

그러나 때로는 컴파일 타임에이를 적용 할 수 있어야합니다. 이 경우 유일한 방법은 몇 가지 트릭을 사용하는 것입니다.

만, 클래스의 노출은 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를의 base class로부터 보호 상속을 사용하여 비슷한 일을 달성 할 수를 포함하는 프록시를 반환합니다.

5

한 가지 방법은 수업을 조금 다르게 재 설계하는 것입니다. 사용되기 전에 초기화해야하는 간단한 데이터베이스 클래스를 고려하십시오. 나는 자바 녀석이다. 그래서 ...

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

그래서 init를 먼저 호출해야한다. 초기화를 수행하고 실제 데이터베이스 객체를 반환하는 DatabaseFactory를 만들 수 있습니다. DatabaseFactory 만 Database를 생성 할 수 있도록 생성자를 숨길 수 있습니다 (Java에서는 중첩 클래스, C++에서는 friend 클래스일까요?).

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"); 
2

보장 할 수있는 한 가지 방법은 클래스의 생성자에서 A을 수행하는 것입니다. 생성자가 실패하면 (throws) 다른 개발자는 무엇을 해야할지와 함께 무엇이든 가지고 있지 않습니다. B. 생성자가 성공하면 A이 적어도 한 번 완료되므로 B이 유효한 연산입니다.

2

"A"메서드를 사용하여 개체를 초기화하는 생성자를 만들 것입니다. 컴파일러가 강제로 객체를 사용하려면 한 번 호출해야합니다.나중에 생성자가 호출되어야한다는 지식에서 메소드 "B"를 호출 할 수 있습니다.

관련 문제