깨지기 쉬운 베이스 클래스 문제(Fragile Base Class Problem)
Fragile/Brittle Base class Problem
- 깨지기 쉬운 베이스 클래스 문제, 깨지기 쉬운 기반 클래스 문제, 취약한 기반 클래스 문제 등으로 불림
- 부모 클래스가 변경되었을 때 자식 클래스에 어떤 영향을 줄 지 모르는 현상
- 베이스 클래스의 인터페이스 변경이 파생 클래스에 예상치 못한 문제를 발생시키는 문제
The fragile base class problem is a fundamental architectural problem of object-oriented programming systems where base classes super classes are considered “fragile” because seemingly safe modifications to a base class, when inherited by the derived classes, may cause the derived classes to malfunction.
- 베이스 클래스의 메서드를 개별적으로 검사해서는 베이스 클래스의 변경이 안전한지 여부를 확인할 수 없음
- 상속과 관련된 일반적인 문제로, 상속을 지원하는 대부분의 언어에서 발생함
대표적인 예시
- 불필요한 인터페이스 상속 문제
- 메서드 오버라이딩 오작용 문제
- 부모클래스와 자식클래스 동시 수정 문제
예시 - 메서드 오버라이딩 오작용 문제
- 위 예시 중, 두번째 예시
초기 상태
1
2
3
4
5
6
7
8
9
10
11
12
class Base {
int counter = 0;
public:
virtual void inc1() { counter++; }
virtual void inc2() { counter++; }
};
class Derived : public Base {
public:
void inc2() override { inc1(); }
};
- 베이스 클래스는 카운터를 증가시키는
inc1()
,inc2()
를 가지고있다 - 파생 클래스는 베이스 클래스를 상속받아
inc2
를 재정의 했다Dervied.inc2()
를 호출하면Base::inc1()
이 호출되어 카운터가 1 증가한다
Fagile Base class problem 발생
- 그러나 베이스 클래스의
inc1()
을 변경한 경우, fragile base class 문제가 발생한다
1
2
3
4
5
6
7
8
9
10
11
12
13
class Base {
int counter = 0;
public:
virtual void inc1() { inc2(); } // 변경됨.
virtual void inc2() { ++counter; }
};
class Derived : public Base {
public:
void inc2() override { inc1(); }
};
- Base 클래스에서
inc1()
는 호출해도 문제가 없으나, Derived 클래스는 문제가 발생함 inc2()
를 재정의 했기 때문에Dervied::inc2()
가Base::inc1()
을 호출하고
Base::inc1()
은Derived::inc2()
를 호출하여 무한 재귀가 발생함!
해결 방법
1
2
3
4
5
6
7
8
9
10
11
12
class Base {
int counter = 0;
public:
virtual void inc1() { Base::inc2(); } // <-- now safe
virtual void inc2() { ++counter; }
};
class Derived : public Base {
public:
void inc2() override { inc1(); }
};
inc1()
을 수정할 때, 명시적으로Base::inc2()
를 호출한다고 작성하면, 무한 재귀가 발생하지 않는다- 추상화 클래스와 템플릿등의 기법을 활용하여 문제를 예방할 수 있음.
- java에서는
final
키워드를 통해 상속을 금지시킬 수 있다고 함
참조 :
Fragile base class
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.