액션스크립트 2.0에서의 클래스 #2

속성 (Properties)

클래스의 정의에서 정보가 저장되는 부분을 속성이라 한다. 정보는 크게 두 가지로 나눌 수 있는데, 한 가지는 그 클래스 자체에 대한 정보이고, 다른 하나는 클래스의 개별 인스턴스에 대한 정보이다. 이해를 돕기 위해 사람이라는 객체를 생각해 보자.  사람에게는 두 개의 눈이 있다. 이 정보는 기본적으로 모든 사람에게 해당 되는 것으로, 사람이라는 객체 자체의 정보라고 볼 수 있다. 그러나 이런 정보 외에 개인의 이름이나 키, 몸무게 같은 정보도 있을 것이다. 이런 정보는 개인마다 다른 속성이 된다. 이렇게 두 가지 서로 다른 속성을 저장하기 위해 클래스의 정의에는 두 가지 서로 다른 속성이 존재한다.

  • 클래스 속성: 클래스 자체의 정보를 저장하기 위한 속성
  • 인스턴스 속성: 개별 인스턴스의 정보를 저장하기 위한 속성

인스턴스 속성은 일반적으로 객체의 상태를 저장하고 있는 경우가 많다. 좀 더 자세히 살펴보면, 인스턴스 속성은

  • 개별 인스턴스마다 서로 다른 값을 가지고 있다.
  • 개별 인스턴스를 통해 접근 가능하다.
  • 어떤 값이 할당 되어도 다른 인스턴스에 영향을 주지 않는다.

흠, 문장이 어렵게 쓰여지고 있다. 좀 많이 고쳐야 할 것 같다. 아니 이번 장은 전체적으로 구성을 다시 새로 바꾸는 작업이 필요할 것 같다. 우선은 내용을 채워 넣는 것이 급하니, 일단 써 놓고 생각해보자. 왠지 번역체가 되어 가는 것같다.

인스턴스 속성을 선언하기 위해서는 다음과 같이 var명령어를 이용한다.

var propertyName:datatype = value;

여기서 propertyName은 속성의 이름을 나타내고, datatype은 그 속성의 데이타타입을 나타낸다. 그리고 value는 이 속성에 초기 값으로 주어지는 값이다. 앞서 얘기한 바와 같이 여기서 datatype을 명시적으로 정의해 주지 않으면, 이 속성에 대해 접근할 때, 데이터타입 검사가 이루어지지 않는다. 만약 value라는 초기값이 지정되지 않으면, 이 속성은 undefined라는 값을 초기값으로 가진다. 이제 앞에서 만들었던 Box라는 클래스에 Number의 데이터타입을 가지는 두 가지 속성, width와 height를 추가해보자.

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

    public function Box() {
        trace(”in the constructor of the Box class”);
    }
}

여기서 속성을 선언할 때 데이터타입을 지정해 주었으므로, 앞서 배운 바와 같이 이 클래스의 인스턴스를 생성하여 height나 width에 Number 타입이 아닌 다른 타입의 데이터를 저장하면 컴파일 에러가 발생하게 된다. 확인을 위해 다음의 스크립트를 실행시켜보자.

var b:Box = new Box();
b.height = “very tall”;

액션스크립트 1.0과 달리 액션스크립트 2.0에서는 이렇게 사용자가 정의한 클래스에 존재하지 않는 속성에 대해 접근하려고 하면 에러가 발생한다. 다음의 스크립트를 실행시켜 보자.

var b:Box = new box();
b.description = “A square object”;

description이라는 속성이 Box 클래스에 존재하지 않는다는 에러가 발생할 것이다. 물론 클래스를 정의할 때 dynamic으로 정의하면 에러가 발생하지 않고, description이라는 속성이 b라는 인스턴스에 새롭게 추가 되는데, 이 dynamic이라는 키워드에 대해서는 뒤에 좀 더 자세히 알아보기로 하고, 우선은 Box클래스에 다음과 같이 description이라는 속성을 하나 더 추가하자.

class Box {
    var width:Number;
    var height:Number;
    var description:String;

    public function Box() {
        trace(”int the constructor of the Box class”);
    }
}

이제 다시 다음의 스크립트를 실행해보자.

var b:Box = new Box();
b.description = “A square object”;

더 이상 에러가 발생하지 않을 것이다. 이걸로 모든 문제가 해결된 것일까? 이런 질문이 나오는 걸 보니 뭔가 문제가 있다는 것을 짐작할 수 있을 것이다.

일반적으로 위의 예와같이 클래스 외부에서 클래스 내부의 속성에 직접 접근하게 하면, 클래스 자체의 유연성이 떨어지게 된다. 즉, 위와 같은 경우 Box클래스의 description이라는 속성의 이름이 너무 길어서 desc로 수정하면, 위 스크립트도 수정해 주어야 한다. 외부에서 직접 접근하는 코드가 하나 뿐이라면 모르겠지만, 만약 프로그램 전반에 걸쳐 위와 같은 스크립트가 존재한다면, 해당 부분을 일일이 찾아서 고쳐줘야 하는 일이 생긴다. 매우 번거로운 일이 아닐 수 없을 뿐더러, 종종 찾기 힘든 에러가 발생하는 원인이 되기도 한다.

이런 경우도 생각해 보자. 만약 Box 클래스의 인스턴스에 width나 height의 값으로 음의 값을 저장하려고 하는 코드가 있다고 하자. 이런 경우 음의 값은 width나 height속성에 유효하지 않은 값이므로, 이런 값이 저장되는 것을 막고 싶어질 것이다. 그런데, 이런 경우를 막을 수 있을까? 클래스의 외부에서 클래스 내부의 속성에 직접 접근할 수 있게 해 두면, 이런 유효하지 않은 값이 속성에 저장되는 경우를 막을 방법이 없게 된다.

위와 같은 문제들 때문에 클래스를 정의할 때 그 클래스의 속성은 보통 private이라는 키워드를 이용하여 정의한다. private과 public에 대해서는 앞서 잠깐 언급한 바가 있는데, 지금부터 좀 더 자세히 알아보자.

private vs. public

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

참고문헌

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