2011년 5월 5일 목요일

자바의 접근지정자(Access Modifiers)

오늘은 여러분이 자바 소스를 볼때 항상 골아프게 만드는 골치거리들을 공부하고 정리하는 시간을 갖고자 한다. 바로 자바의 접근 지정자(Access Level Modifiers)에 대해서 살펴보기로 하겠다. 저번에 자바의 상속 부분을 긴 예제를 통해 공부하느라 힘(?)이 다 빠졌을 것이니 오늘은 특별히 머리도 식힐겸 예제가 없이 필자의 능란한 화술(?)에 의존해서 옛날 이야기를 통해 본 강좌를 진행해볼까 한다. 그렇다고 아무 생각없이 멍(?) 때리면서 들어서는 안된다. 최소한의 성의(?)를 보이는 자만이 이번 강좌의 과실을 따먹을수 있을 것이라고 강력 선포한다.^^ 농담이다. 설렁설렁 들어도 다 알아먹게끔 만들어 주겠다.ㅎㅎ

자바의 접근 지정자는 아래처럼 멤버의 종류를 나타내는 기호 앞에 위치한다.
public class Parent {......}   //public의 예
protected void move( ) {......}   //protected의 예
int a;
//(no modifier)=(default)=(friendly) 모드는 평상시처럼 쓰지 않았을때 해당
private int a;   //private의 사용예

접근 지정자는 public, protected, (no modifier), private 이라고 불리는 것들로 접근 레벨이 네가지로 나뉘는데 지금 쓴 순서대로 접근 제한의 강도가 세진다. public은 뭐 말 그대로 제한없이 쓸수 있는거고 예제에서 봤겠지만 아직은 있으나 없으나 별 체감이 없을 것이다. 필자가 프로그램 짜면서 특별히 어떤 멤버들을 접근못하게 막은적이 없으니까 말이다. private은 말그대로 사적인거니까 자기자신 빼고는 다 접근못하게 막은거라 추론이 가능하다. 나머지는 중간에 있는걸로 봐서 뭐 중간 형태이지 않겠냐? ㅎㅎ 그럼 접근 지정자가 왜 필요한지 잠시 토픽(영어시험 아님-.-)에 관련된 이야기를 해보겠다.

해외에서 살고있는 한 가족의 이야기이다. 자바섬이라는 곳이 있는데 그곳에 "라이"라고 불리는 한 가장의 가족들이 살고 있었다. 그는 아내를 젊은 나이에 교통사고로 잃고 남겨진 아들 "테디"와 사고후 얼마안되어 그 사고를 잊지못하는 아들을 위해 그의 친구인 "폴"을 불러 외로움을 덜어주게 하고 몇년이 지난후 폴을 양아들로 받아들여 함께 살았다. 라이는 자바섬에서 다른 이들과는 달리 불굴의 노력과 의지로 드물게 성공하여 엄청난 부를 거머쥐었다. 라이는 모든 재산을 자신의 계좌에서 스스로 관리해왔는데 이제 아이들도 장성하여 필요한 일이 있을경우 쓸수있도록 본인의 계좌에 접근가능한 법인카드를 자신의 친아들 테디와 양아들 폴에게 주며 "같은 집에서 사는 이상 너희들은 똑같은 나의 자식들이다"라며 많은 부를 그들에게 물려주었다. 그러나 어느날 폴은 이제 자바섬이 지겨워졌다며 떠나려하자 라이는 떠날 경우 그동안 베풀었던 모든 것을 거둬들이겠다고 한다. 결국 폴은 그에 아랑곳 하지않은채 말없이 떠나고 라이는 떠남을 슬퍼하지만 약속은 약속인지라 계좌접근을 차단시키고 자식이라는 점은 변한게 없으니 침묵한다. 그러기가 수십년, 어느날 "빌리"라는 청년이 찾아와 자바섬을 살리기 위해선 라이의 도움이 필요하다고 요청하고 오랫동안 간청한 끝에 라이는 빌리의 의견을 결국 수락하여 사회에 자신의 전재산을 환원하여 모든 이가 라이의 기부(?) 덕분에 행복하게 살았다는 이야기다.*

출연진: 라이-private, 폴-(default=friendly), 테디-protected, 빌리-public
상속시 오버라이드를 통해 멤버들 재정의할때도 접근지정자를 위의 출연진 차례처럼 접근 강도를 완화시켜가는 것은 가능하지만 반대로 강화시키는건 불가능하다는 점을 기억하기 바란다.

접근 지정자는 이럴때 필요하다. 라이가 은행계좌를 가지고 있는데 당연히 자기자신만 그 계좌에 접근할수 있어야한다. 이런 의미로 쓰는게 private이다. 그런데 상황에 따라 누군가에게는 접근가능하게 만들어 주어야 할때가 있다. 다른 것들은 놔두고 양아들 폴처럼 자식이라도 다른데 있을때는 접근을 제한할때가 생긴다. 이런 의미로 해당하는 것이, 아무것도 쓰지 않았을때 자바에서 자동으로 작동하는 (no modifier) 디폴트에 해당한다. 그리고 남을 제외하고 테디나 폴처럼 관련 가족에게는 모두 접근할수 있도록 권한을 준다. 이런 의미로 쓰는게 protected이다.  마지막으로 빌리가 요청한 것처럼 어디서나 누구나 모든 이가 쓸수 있게 되면 그것은 public에 해당한다. 읽으면 읽을수록 참 훌륭한 필자의 창작 이야기다. ㅎㅎㅎ

그럼 이제는 접근 지정자들의 접근가능 범위를 요약해 보겠다.


1. (자기자신) 같은 클래스(class)에서 접근가능
2. 같은 package에 있는 자식(extends한) 클래스에서 접근가능
3. 같은 package에 있는 다른 클래스에서 접근가능
4. 다른 package에 있는 자식 클래스에서 접근가능
5. 다른 package에 있는 다른 클래스에서 접근가능

public: 1, 2, 3, 4, 5 (모두 가능)
public 명령어는 클래스, 인터페이스,
생성자, 내부 클래스, 메소드, 필드 변수들 이름 앞에 붙여 사용함.
사용예제:   public int a;

protected: 1, 2, 3, 4 (가능하고 나머진 불가능)
protected 명령어는
생성자, 내부 클래스, 메소드, 필드 변수들 이름 앞에 붙여 사용함.
사용예제:   protected int a;

(no modifier): 1, 2, 3 (가능하고 나머진 불가능)
default 디폴트 명령어는 말그대로 쓰지 않았을때 자동으로 인식한다.
자바코드 보다가 아무것도 안써있으면 다 이 모드라고 생각하면 된다.
사용예제:   void add( )
같은 패키지에서는 접근 가능하고 다른 패키지에서는 불가능하다고 하여
"package-private 패키지 프라이빗"이라고도 불린다.
생성자, 내부 클래스, 메소드, 필드 변수들 이름 앞에 아무것도 안붙이면 됨.
사용예제:   int a;

private: 1 (하나만 가능하고 나머진 불가능)
private 명령어는 클래스, 인터페이스,
생성자, 내부 클래스, 메소드, 필드 변수들 이름 앞에 붙여 사용함.
사용예제:   private int a;

여러분이 아직은 package 패키지란 것이 익숙하지 않을테니 그림을 통해 부가 설명을 하겠다. 강좌 초반에 import를 설명하면서 패키지에 대해서 약간 말한적이 있는데 기억날지 모르겠다. 디렉토리 같은 개념으로 생각하면 된다. 디렉토리마다 어떤 분류로 파일들을 모아놓지 않는가? 그것처럼 패키지마다 분류별로 자바의 클래스 파일들을 모아놓은 꾸러미라고 생각하면 이해가 쉬울 것이다. 보다 자세한 사항은 본 강좌의 import 관련 부분을 찾아서 보기 바란다.


패키지1 안에 Alpha 클래스와 Beta 클래스가 들어있다. 패키지2 안에는 AlphaSub 클래스와 Gamma 클래스가 들어있다. 이중 Alpha 클래스는 AlphaSub 클래스의 부모이다. 화살표는 extends한 클래스가 Alpha 즉 부모 클래스라는 것을 가리키고 있다. 이런 상황일때 Alpha 클래스 멤버들을 지금까지 배웠던 네가지 접근 지정자에 따라서 다른 클래스에서 접근이 가능한지 못한지를 알아보기 위한 그림 예제이다.

Alpha 클래스에서는 Alpha 클래스 멤버들이니 너무 당연하지만 private을 포함 어떤 접근 지정자로 해놓든 다 사용할수 있다. 그럼 Beta 클래스의 경우를 보자. Beta 클래스는 같은 패키지안에 있다. 이럴 경우 private만 빼고 어떤 접근 지정자가 쓰였더라도 관계없이 Alpha 클래스 해당멤버를 불러서 쓸수 있다. AlphaSub 클래스는 자식 클래스인데 다른 패키지안에 있다. 다른 패키지이면 설사 자식 클래스라 하더라도 (no modifier) 아무것도 앞에 없는 디폴트일 경우와 private일 경우 접근이 불가능하여 그 해당멤버를 쓸수가 없다. 마지막으로 Gamma 클래스는 Alpha 클래스와 패키지도 다르고 부모 자식인 상속 관계에 있지도 않다. 따라서 Alpha 클래스 멤버가 public 모드가 아니면 모두 접근이 불가능하다.

오케이? ㅎㅎ 자바의 접근 지정자에 대해서 알아보았다. public과 private은 극과 극이므로 비교적 알기 쉬운데 반해 protected와 (default)인 경우에는 어떤 곳에서 접근해 쓸수 있는지 잦은 혼란을 초래하기 때문에 많은 이들이 어려워한다. 다시 정리하자면 protected와 (default) 모드는 방금 그림에 있는 예처럼 다른 패키지에 있는 자식 클래스에서 접근이 가능한지 불가능한지로 구분할수 있다. 접근이 가능하면 모드가 protected 일때고 접근이 불가능하면 (default) 투명모드로 멤버를 만들어놨기 때문이다. 그래서 디폴트 모드를 자식 클래스라도 다른 패키지에 있으면 접근 못하니까 영어로 package-private 패키지 프라이빗이라고 부른다. 지금 보니 이 단락만 이해하면 끝이네.ㅎㅎ 그래도 위의 내용을 읽었으니까 지금 이 단락을 쉽게 이해했다고 생각하자. 아님 고달프다.-* 오늘은 여기까지다.^^

댓글 8개:

  1. 역시 감탄 또 감탄

    답글삭제
  2. 문장가이십니다.
    책을 한번 쓰심 어떨까 아룁니다.

    답글삭제
  3. I'm not sure why but this site is loading very slow for me. Is anyone else having this issue or is it a problem on my end? I'll check back later and
    see if the problem still exists.

    Here is my page; anti cellulite treatment

    답글삭제
    답글
    1. 저두 가끔 로딩이 느릴때 있으나, 지역차이 아닐까여????

      서버는 한국이니까 한국이 빠르겠졍. ...

      삭제
    2. Same here (U.S.). I have a problem with loading this page. It's very slow, guessing because of pulling out so many ads gadgets.

      삭제
  4. 한국에서 접속중이지만 느림 ... ;ㅅ; 그렇다고 공부하는데
    방해요인이 되지는 않아요 ㅎㅎ

    답글삭제