'은닉화'에 해당되는 글 2건
- 2008.08.14 캡슐화,은닉화(Encapsulation)-2
- 2008.08.14 캡슐화,은닉화(Encapsulation)-1
아마 여러분은 굳이 텔레비전의 내부를 뜯어보지 않아도 리모콘을 통해 텔레비전을 사용할 수 있을 것입니다. 또는 자동차가 어떻게 작동하는 지 알지 못해도 운전하는 방법만 알고 있다면 자동차를 운전할 수 있을 것입니다. 설사 여러분이 운전을 할 수 있다고 하더라도 실제로 자동차의 엔진 내부를 뜯어본 사람은 별로 없을 것입니다. 엔진은 자동차에게서 가장 중요한 부품이 아닙니까? 오히려 엔진 내부를 뜯어봤다면 아마도 그 자동차는 제대로 작동하지 않을 지도 모르죠. 자동차 정비소에서 엔진을 한번 볼 기회가 있었는데 캡슐같이 생긴 통안에 머리카락이라도 보일까봐서 아주 깊숙히 꼭꼭 숨어있더라고요. 이렇게 꼭꼭 숨어있다고 하더라도, 그것이 엔진이 어떻게 작동되는 지 세부적인 사항을 알지 못하더라도 우리는 이 엔진을 손쉽게 작동시킬 수 있습니다. 자동차가 제공하는 엑셀레이터를 통해서 말이죠. 이것이 객체지향 방법론에서 말하는 캡슐화라고 하는 것입니다.말 그대로 중요하고 세부적인 구현 방법에 대한 자세한 사항은 캡슐 안에 꼭꼭 숨겨놓는 것입니다. 자동차에게 중요한 것이 엔진이라면 소프트웨어 시스템에게 있어서 중요한 것은 데이터입니다. 그래서 캡슐화를 데이터 감추기(data hiding)라고도 하는 것이지요.
----------------------------------------------------------------------------------------
여기서 주의깊게 살펴봐야 하는 부분을 색으로 표시하였다. 우리가 엔진이 어떻게 작동하는지 알지 못해도 엑셀레이터를 이용해 자동차를 움직이게 할 수 있는것처럼 메소드나 클래스의 내부가 어떻게 동작하는지 알 지 못해도, 그 클래스에서 사용하는 기능을 이용하여 문제를 해결할 수 있다.
아래의 예를 보자
Math.round(12.5);
위의 코드는 12.5를 반올림해서 결과값을 반환해준다. 우리는 Math라는 클래스가 어떻게 생겼는지, 어떻게해서 round 메소드에서 반올림이 이루어지는지 전혀 알지 못한다. 단지, Math.round()의 괄호안에 숫자를 집어넣으면 반올림이 된다는 사실만 알고있고, 그것을 이용할 뿐이다.
이전 포스트에서 자동차의 좌석수를 지정하고 이용하기 위해서 setter와 getter메소드를 이용하였다. 이때, 사용자는 어떻게 데이터가 setting되고, 어떻게 데이터가 반환되는지에 신경쓸 필요가 없이 setter와 getter가 어떤역할을 하는지만 안다면, 이전 포스트처럼 값을 대입해서 이용하기만 하면 된다. 이처럼 실제로 구현되는 부분을 외부에 드러나지 않도록 캡슐로 감싸 이용방법만을 알려주는것이 캡슐화의 중요 컨셉이다.
그리고, 이 캡슐화 과정에서 데이터들과, 여러 로직들이 은닉된다. 캡슐로 감싸 숨기는 것이다.
내가 생각하는 캡슐화와 은닉화의 차이점을 정리하자면 은닉화는 중요사항이(변수던 메소드던간에)밖으로 드러나지 않도록 꼭꼭 감추는것을 의미한다면, 캡슐화는 중요사항을 감춘 상태에서 외부에 그것을 사용할 수 있는 방법을 설정하고, 외부와 직접적으로 의사소통을 의미 한다는 점이 차이점이 될 것이다.
아래의 예는 Headfirst Design Patterns중 Strategy Pattern예제이다.
사진을 클릭하면 원본 크기의 사진을 볼 수 있다.
위의 예에서 오리에게는 날거나 꽥꽥거리거나 하는행동이 필요하다. 이때, 날거나 꽥꽥거리는 행동을 각 오리마다 따로 코딩한다는것은 코드의 유지보수면에서 대단히 안좋다. 이런때, 날거나 꽥꽥거리는 행동을 각각 캡슐화 해서 날고 싶을때는 위쪽 사각형의 나는 행동의 캡슐화 해좋은 부분에 메소드를 사용하고, 꽥꽥 거리고 싶을때는 꽥꽥 거리는 행동을 캡슐화 해놓은 메소드를 사용하면 된다. 이때 나는것은 fly()메소드를 이용하고, 꽥꽥거리는것은 quack()메소드를 이용한다.
이처럼 캡슐화는 감출것은 감추고 사용법만 알려주어, 편하고 쉽게 코드를 이용또는 재사용 할 수 있게 해준다.
** 위 uml의 예제코드는 생략한다.
'My work space > Java' 카테고리의 다른 글
use-a 복합연관(composition) (0) | 2008.08.14 |
---|---|
has-a 집합연관(aggregation) (0) | 2008.08.14 |
캡슐화,은닉화(Encapsulation)-1 (0) | 2008.08.14 |
개발자가 놓치기 쉬운 자바의 기본원리 (0) | 2008.08.14 |
아스키 코드표 (0) | 2008.08.14 |
흔히들 캡슐화와 은닉화를 동일선 상에서 놓고 보는것 같다. 꼭 그런것은 아니지만, 몇군데 검색해서 찾아보면 캡슐화와 은닉화를 같다고 이야기 하는 경우를 종종 볼 수 있다. 내가 좋아하는 책인 O'Reilly의 Headfirst Java책에도 캡슐화를 데이터 은닉과 같게 취급하고 있다.
물론, 캡슐화나 은닉화로서 나온 결과물이 비슷하다는 점에서 그 둘을 같다고 볼 수 있겠지만, 개인적인 생각으로는 캡슐화와 은닉화의 개념을 좀 구분지어야 하지 않을까 싶다. 결론부터 얘기하자면
"캡슐안에 데이터를 숨긴다"
정도가 되겠다.
여기에는, 캡슐이 있고 데이터가 있다. 캡슐과 데이터는 엄연히 다른것이다. 데이터는 프로그래밍에서 변수로 쉽게 취급될 수 있지만, 캡슐이 메소드 단위를 의미하는지, 클래스 단위를 의미하는지, 아니면 프로젝트 단위를 의미할 것인지는 불분명 하다. 요는 캡슐화가 데이터은닉에 비해 훨씬 추상적인 개념이라는 것이다.
데이터 은닉을 표현하는것은 쉽다. 만약 자동차의 좌석수를 설정한다고 해보자. 자동차라는 클래스가 있고, 어딘가 다른 클래스에서 그 자동차의 좌석수를 아래와 같이 설정한다고 하자.
---------------------------------------------------------------------------
Car myCar = new Car();
myCar.numberOfSeat = 3; // numberOfSeat 는 Car의 변수
---------------------------------------------------------------------------
Car내부의 numberOfSeat라는 변수를 직접 접근해서 값을 설정하고 있다. 하지만 자동차의 좌석수는 적어도 1개보다 많아야 한다. 만약 아래와 같이 설정한다면 어떻게 될것인가..
---------------------------------------------------------------------------
Car myCar = new Car();
myCar.numberOfSeat = 0; // numberOfSeat 는 Car의 변수
---------------------------------------------------------------------------
어처구니 없지 않은가.. 자동차의 좌석수가 0이라니.. 이순간 우리는 좌석이 하나도 없는 자동차를 갖게 되는 것이다. 이런일은 있을 수 없으며 또, 이런일이 발생하지 않도록 좌석의 수가 1보다 클수있도록 제제를 가할 방법이 필요하다. 어떻게 하면 되겠는가?
1. 먼저 데이터를 곧바로 접근해서 맘대로 값을 할당할 수 없도록 해야한다 :
Car내부의 numberOfSeat변수의 접근자를 public 에서 private로 변경해 주면 된다.
---------------------------------------------------------------------------
// Car 내부...
public int numberOfSeat -> private int numberOfSeat
---------------------------------------------------------------------------
이제 외부의 어떤 클래스도 Car내부의 numberOfSeat을 함부로 건드릴 수 없게 되었다.
2. 값을 설정하거나, 불러올때 : getter와 setter를 사용하면 된다.
---------------------------------------------------------------------------
// Car 내부...
public void setNumberOfSeat(int n)(){
if(n>=1) numberOfSeat = n; // 만약 1보다 크거나같다면
} // 내부변수에 값 할당
public int getNumberOfSeat()(){
return numberOfSeat; // 내부변수값 보내주기
}
---------------------------------------------------------------------------
3. 마지막으로, 외부의 클래스에서 아래와 같이 사용하면 된다
1) 값을 대입할경우 : myCar.setNumberOfSeat(4)
2) 값을 받아올경우 : myCar.getNumberOfSeat()
만약 값을 대입할때, myCar.setNumberOfSeat(0)을 한다면 어떻게 될까.. 당연히 컴파일 에러가 발생할 것이다. 즉, 앞으로는 1보다 작은값이 절대 들어갈 수 없게 되는 것이다. 이로서 데이터의 무결성 또한 보장된다.
은닉은 밖으로 들어나지 말아야 하는것을 철저하게 감추는 것을 의미 한다. 따라서 클래스 내부적으로만 사용해야 하는 메소드들도 모두 private로 설정해야 함을 잊지 말아야 할 것이다.
'My work space > Java' 카테고리의 다른 글
has-a 집합연관(aggregation) (0) | 2008.08.14 |
---|---|
캡슐화,은닉화(Encapsulation)-2 (0) | 2008.08.14 |
개발자가 놓치기 쉬운 자바의 기본원리 (0) | 2008.08.14 |
아스키 코드표 (0) | 2008.08.14 |
JAVA SDK API 1.5 한글번역문서 (0) | 2008.08.14 |