private vs. public

private vs. public

private이나 public과 같은 키워드를 접근 한정자(access control modifier)라고 한다. 왜냐하면 클래스의 외부에서 해당 접근할 수 있는가 없는가를 결정지어 주기 때문이다.

객체지향 프로그래밍에서 중요한 개념들 중 하나로 캡슐화라는 것이 있다. 한 객체의 내부의 정보는 외부에서 직접적으로 접근할 수 없도록 해 두고 외부에서 그 객체 내부의 정보에 접근하기 위해서는 그 객체가 제공하는 메소드를 이용하도록 하는 것이다. 이렇게 해 놓으면 객체 내부의 구조가 아무리 바뀌어도 그 객체가 제공하는 메소드가 제대로 된 정보만 제공해 준다면 외부 프로그램의 입장에서는 전혀 문제될 것이 없게 된다. 다른 객체의 내부 사정은 남의 일 일뿐인 것이다.

이런 객체지향 프로그래밍의 캡슐화를 위해 제공하는 도구가 바로 이 접근 한정자다. 객체 내부의 속성은 private으로 지정하고 , 외부에서 그 속성에 접근할 필요가 있을 경우에는 그 속성에 접근 가능한 메소드를 클래스에 정의해 두고 외부에서 접근할 수 있도록 public으로 선언해 주는 것이다. 이 때 일반적으로 이 속성에 접근하기 위한 메소드의 이름은 속성의 이름 앞에 set이나 get을 붙여준다. 이렇게 이름을 지으면 메소드 이름만 봐도 어떤 속성에 접근하기 위한 메소드인지 외부 프로그램을 작성하는 사람이 쉽게 알 수 있기 때문이다. 또한 이런 메소드들을 일컬어 setter와 getter라고 부른다. 예를 들면 다음과 같다.

class Box {
    private var width:Number;
    private var height:Number;

    public function Box() {
    }

    public function getWidth():Number {
        return width;
    }

    public function setWidth(newWidth:Number):Void {
        width = newWidth;
    }
}

이 스크립트에서는 Box 클래스의 속성인 width와 height가 둘 다 private으로 선언되어 있다. 그리고, width 속성에 접근하기 위한 메소드가 두 개 더 선언 되어 있는데, width라는 속성의 이름 앞에 set-과 get-을 붙인 getWidth()와 setWidth()가 그것이다. 이제 이 클래스의 외부에서 인스턴스를 생성하여 width와 height 속성에 접근해 보자.

var b:Box = new Box();
b.setWidth(30);
trace(b.getWidth);
b.height = 30;
trace(b.height);

이 스크립트를 실행해보면 다음과 같은 결과를 얻게된다.

classes-private-exedra.jpg

앞의 width의 경우 외부에서 접근할 수 있는 setter와 getter가 정의 되어 있으므로, 접근이 가능한 반면, height의 경우 그런 메소드가 정의되어 있지 않으므로 오류가 발생하는 것이다.
캡슐화와 관련된 예제를 하나 더 살펴보기 위해 다음과 같이 위의 Box클래스를 수정하자.

class Box {
    private var width:Number;
    public var height:Number;

    public function getWidth():Number {
        return width;
    }

    public function setWidth(newWidth:Number):Void {
        if (newWidth < 0) {
            trace(“Error: Box’s width can’t be negative”);
        } else {
            width = newWidth;
        }
    }
}

여기서는 height를 public으로 바꾸었고, setWidth()의 정의가 조금 복잡해졌다. 내용을 살펴보면, Box객체의 width를 설정할 때, 만약 음의 값이 들어오면 오류메시지를 보여주고, 아니면 그 값을 객체의 width에 저장하는 것이다. 이제 다음의 스크립트를 클래스의 외부에서 실행해보자.

var b:Box = new Box();
b.height = -10;
b.setWidth(-10);
trace(“height=” + b.height + “, width=” + b.getWidth());

다음과 같은 결과를 얻게 된다.

classes-private2-exedra.jpg

컴파일러가 오류를 발생시키지는 않지만, 런타임에 잘못된 값이 Box객체의 width에 할당되었다는 메시지를 확인할 수 있다. 게다가 height의 경우에는 할당되는 값에 대한 어떤 검사도 하지 않으므로, -10이라는 의미없는 음의 값을 저장하고 있고, width의 경우에는 setWidth()에서 할당하기 전에 먼저 검사를 통해 부적절하다고 판단하여 할당하지 않았으므로, undefined라는 값을 가지고 있음을 알 수 있다.

참고문헌

  • An Introduction to Object-Oriented Programming 2nd edition, Timothy Budd, Addison Wesley
  • Essential ActionScript 2.0, Colin Moock, O’Reilly