이번에는 singleton 클래스를 상속하는 것에 대해서 얘기를 해 보겠습니다. 얘기를 시작하기 이전에 곰곰히 생각해 볼 문제가 있습니다.

"과연 singleton 객체의 상속은 타당한가?"


예를 들어 보겠습니다. App라는 클래스가 있고 이는 singleton pattern이며 instance()라는 메소드로 객체에 접근을 할 수가 있다고 가정을 합니다. 이 상태에서 프로그래머는 MyApp라는 클래스를 App에서 상속을 받고 싶어 합니다.

class App {
public:
  static App& instance();
};

class MyApp : public App {
};

잘 생각해 보면 문제가 복잡해 집니다. App::instance()라는 메소드를 활용하면 App 클래스 객체가 반환되지 MyApp 클래스 객체를 반환되어 지지가 않습니다. 따라서 MyApp 클래스에서도 똑같이 별도의 메소드를 제공해야 한다는 결론에 도달할 수 있습니다.

class MyClass : public App {
public:
  static MyApp& instance();
};

이렇게 되면 의아한 결과를 낳을 수 있습니다. 왜냐 하면 어플리케이션 코드에서 App::instance() 와 MyApp::instance()를 호출하게 되면 App 객체 하나, MyApp 객체 하나 해서 2개의 instance가 생기게 됩니다. 결국 “single 클래스의 객체는 하나뿐이다” 라는 원래의 취지를 위반하게 되죠.

  • singleton 클래스를 상속을 받게 되면 하위 클래스에서도 부모 클래스와 마찬가지로 인터페이스에 접근할 수 있는 메소드를 별도로 또 제공해야 한다.

  • singleton 클래스는 상속을 받게 되면 클래스 갯수만큼 instance가 여러개 생성될 수 있다.

  • 그러므로 singleton 클래스는 애시당초 상속이 되지 않도록 하는 것이 좋다.

C++에서 클래스 상속을 원하지 않는 경우라고 한다면 클래스(App)의 모든 constructor 혹은 destructor를 private으로 선언을 하여 상속을 방지할 수가 있습니다(상속을 방지하기 위해서 java에서는 final이라는 keyword가 제공되는데, C++에서 이와 비슷하게 해 보려고 이렇게 저렇게 template를 만들어 구현을 해 보려고 하였지만 올바른 방법을 도출할 수가 없더군요).

참고로 클래스의 모든 멤버 객체들을 전부 static으로 선언해 버리는 Monostate Pattern 이라는 것도 있으니 참고하시기 바랍니다. 이 경우 class라는 예약어보다는 차라리 namespace라는 예약어를 사용하는 것이 더 직관적일 것입니다.

출처 : gilgil.net