데이터 맴버가 왜 public, protected가 되면 안되는지 알아보자.
일단 public이 왜 안되냐.
- 문법적 일관성(항목 18 참고)
만약 데이터 맴버가 public이 아니라면, 사용자 쪽에서 어떤 객체에 접근할 수 있는 유일한 수단은 맴버 함수 뿐이다. 어떤 클래스의 public 인터페이스에 있는 것들이 전부 함수뿐이라면, 그 클래스의 맴버에 접근하고 싶을 때는 무조건 괄호를 붙여야하니 이와 관련된 생각을 안할 수 있다.
- 접근 제어
이게 별로 와닿지 않는 사람도 있을건데, 함수를 사용하면 데이터 맴버의 접근성에 대해 훨씬 정교한 제어를 할 수 있다. 만일 어떤 데이터 맴버를 public으로 내놓았다면 모두가 이 맴버에 대해 읽기,쓰기,접근 권한을 가질 것인데, 이 값을 읽고 쓰는 함수가 있으면 접근 불가, 읽기 전용 등등 접근 권한에 대해 우리가 직접 customising 할 수 있다.
이런식으로 가능
이런 식의 세밀한 접근 제어는 좀 중요하다. 어떤 식으로든 외부에 노출시키면 안되는 데이터 맴버들이 꽤 많기 때문이다.
- 캡슐화
사실 이것 말고 제일 중요한 이유가 있다. 바로 encapsulation 때문이다.
함수를 통해서만 데이터 맴버에 접근할 수 있도록 구현해 두면, 데이터 맴버를 나중에 계산식으로 대체할 수도 있을 것이고, 여튼 사용자는 절대로 이 클래스를 넘볼 수 없게 된다.
즉 캡슐화의 가장 중요한 덕목인 복잡한것은 숨기고, 간단한거만 보여주는 것을 가능케 한다.
======================================================
데이터 맴버를 함수 인터페이스 뒤에 감추게 되면(private으로 만들면 == 캡슐화 시키면) 구현상의 융통성을 전부 누릴 수 있다. 예를 들어 이런 것들이 간편해진다.
- 데이터 맴버를 읽거나 쓸 때, 다른 객체에 알림 메세지를 보내기
- 클래스의 불변성 및 사전조건(precondition), 사후조건(postcondition)을 검증하기
- 스레딩 환경에서 동기화 하기
등등.. (C#, Delphi의 property와 똑같음)
중요한 것은 데이터 맴버를 숨기면, 클래스의 불변속성을 항상 유지하는 데 절대로 소홀해질 수 가 없게 된다. 왜냐하면 클래스가 불변속성을 지닌다는 것을 보여줄 수 있는 통로가 맴버함수 밖에 없기 때문이다.(프로그래머의 의도에 맞게 클래스의 성질이 변하지 않고 잘 지켜지고 있다는 것을 검증할 수 있는 방법이 맴버함수밖에 없음)
그 뿐 아니라, 캡슐화는 현재의 구현을 나중으로 결정할 수 있는 권한을 예약하는 것이다. public으로 되어있는 부분은 한번 클래스를 공개하고 나면 고치기가 매우 힘들다. 손대면 이걸 사용하고 있던 사용자들의 코드가 깨질 것이기 때문이다. C++에서 public = '캡슐화되지 않았다' = '바꿀 수 없다'
===================================================
protected도 마찬가지이다. 문법적 일관성, 접근제어는 public이랑 똑같이 적용되는 것이고, 캡술화는?
항목 23에 이런내용이 나온다. 어떤 것이 바뀌면 깨질 가능성을 가진 코드가 늘어날수록, 캡슐화의 정도는 그에 반비례해서 작아진다.
어떤 클래스에서 public 데이터 맴버가 있고, 이것을 제거한다고 가정해보자. 이 맴버를 사용하는 모든 코드가 영향을 받는다(깨진다). 이제 어떤 protected 데이터 맴버를 제거한다고 생각해보자. 이 맴버를 사용하는 derived class들은 전부…. 엄
public과 protected의 차이는 그것뿐이다. 밖에서 누드쇼를 하냐 아니면 건물 안에서 누드쇼를 하냐이다. private는 내 방안에서 누드쇼를 하든 뭘하든 상관이 없다.
결국,
private = 내 방 = 남한테 안보임 = encapsulation
public, protected = 어쨌든 밖 = 남한테 다 보임 = encapsulation 아님
- 데이터 맴버는 private으로 선언하자. 이를 통해 문법적 일관성, 세밀한 접근 제어, 클래스의 불변속성을 강화, 내부 구현의 융통성도 발휘 가능
- protected는 public보다 더 많이 '보호'받는 것이 절대 아니다.
'Effective C++ > 4. 설계 및 선언' 카테고리의 다른 글
항목 24: 타입 변환이 모든 매개변수에 대해 적용되어야 한다면 비멤버 함수를 선언하자. (0) | 2021.04.24 |
---|---|
항목 23: 함수보다는 비멤버 비프렌드 함수와 더 가까워지자 (0) | 2021.04.24 |
항목 21: 함에서 객체를 반환해야 할 경우에 참조자를 반환하려고 들지 말자. (0) | 2021.04.24 |
항목 20: '값에 의한 전달'보다는 '상수 객체 참조자에 의한 전달' 방식을 택하는 편이 대개 낫다. (0) | 2021.04.24 |
항목 19: 클래스 설계는 타입 설계와 똑같이 취급하자. (0) | 2021.04.24 |