[C++Builder] property 의 유용성

C++ 배울 때 제일 처음 당황하는 것은 private 과 public 키워드이다. '정보의 은닉'이라는 표현은 꽤 묘한 느낌을 주면서도 쉽게 와닿지 않는다. '정보의 은닉', '추상화' , '객체지향' , 'OOP' 등의 단어만 나열하다 끝나는 경우가 많다. 단어가 중요한 것이 아니다. 추상화면 어떻고 정물화면 어떤가 보기 좋으면 그만이다. 단어와 단어가 서로 꼬리를 물며 끝나지 않을것 같은 개념설명에만 매달리지 말고 그냥 쉽게 설명하면 된다.

쉬운 예로 달력을 생각해 보자. 달력은 1년 12달로 구성되어 있다. 13번째 달은 있을수가 없다. 이 클래스의 사용자가 이걸 모르고 13번째 달을 입력하려고 할 수 있다. 정보의 은닉이란 표현은 이런 경우 오동작을 하지 않도록 안전한 처리방법을 제공하겠다는 뜻이다. 만약 사용자가 13번째 달을 입력하지 못하도록 하려면 어떻게 해야 할까. 보통의 C++이라면 다음과 같이 구성한다. 처리방법은 여러가지가 있으나 잘못된 값이 입력되면 그냥 메시지를 출력하고 거부해 버리는 것으로 한다. 13을 입력하면 자동으로 상한값인 12로 바꾸어 버리는 방법도 있다.

class TCalender
{
private:  
  int Month;
public:  
  int GetMonth();  
  void SetMonth(int Value);
};

int TCalender::GetMonth()
{  
  return Month;
}

void TCalender::SetMonth(int Value)
{  
  if((Value < 1)||(Value > 12))  
  {    
     cout<<Value<<" is out of range."<<endl;    
     return;  
  } 
  if(Month != Value)     Month = Value;
}


 문제는 이렇게 할 경우, GetMonth, SetMonth 를 알아야 한다는 것이다. Get, Set 으로 이름을 통일하면 그나마 쉽겠지만, 함수의 이름을 알아야 한다는 점에서 여전히 불편하고 어색하다. 그냥 Month 로 읽고, 쓰기가 되었으면 좋겠지만, 그럴 경우 변수가 직접 외부에 노출되어 버린다. 위와 같은 방식은 변수를 외부에 노출시키지 않게 함으로서 변수의 용도를 모르는 외부인이 함부로 조작하지 못하도록 하는 효과는 있으나 사용하기가 불편해지고 마는 단점이 있다.

이런 문제를 해결해주는 것이 C++Builder, Delphi 에서 추가된 property 키워드이다. property 를 이용하여 위의 소스를 다시 작성해보면 다음과 같다.


class TCalender
{
private:
  int FMonth;
  void SetMonth(const int Value);
public:
  __property int Month = {read = FMonth, write = SetMonth};
};


void TCalender::SetMonth(const int Value)
{
  if((Value < 1)||(Value > 12))
  {
    cout<<Value<<" is out of range."<<endl;
    return;
  }  if(FMonth != Value)
    FMonth = Value;
}
달라진 것을 무엇일까? 외부로 노출된 것은 Month property 이다. 내부로 들어간 것은 변수인 FMonth와 조작하는 함수인 SetMonth 이다. 이게 무슨 차이가 있나? 차이가 있다. 첫번째 소스에서는 함수를 호출하여야 한다. 하지만 두 번째 소스에서는 마치 변수를 직접 조작하는 느낌을 준다.

변수인 FMonth 뿐만 아니라 값을 넣는 함수인 SetMonth 까지 private 에 넣으면 외부에서는 Month 만 보이게 된다. 그뿐만이 아니다. 나중에 값을 읽을 때 따로 처리해야 하는 루틴이 필요하면 property 에서 read = GetMonth 로 하고 GetMonth 함수를 만들어 주면 된다. 이 경우에도 외부에 노출되는 것은 Month 뿐이다. 값을 조작하는 방법이 변해도 외부에 노출되는 것은 변하지 않으므로 이 클래스를 사용하는 소스를 고칠 필요가 없다.

게다가 처음에는 public 에 int Month; 로 선언하고 나중에 조작해야 하는 루틴이 필요할경우 Month 를 property 로 만들고 int Month; 를 int FMonth; 로 해서 private: 에 넣으면 그만이다. 조작방법이 어떻게 변하든 외부에서는 Month 만 보이기 때문이다.

class TCalender
{
private:
public: int Month;
};

초기 작성된 Class



class TCalender
{
private:
  int FMonth;
  void SetMonth(const int Value);
public:
  __property int Month = {read = FMonth, write = SetMonth};
};

SetMonth 추가


class TCalender
{
private:
  int FMonth;
  int GetMonth();
  void SetMonth(const int Value);
public:
  __property int Month = {read = GetMonth, write = SetMonth};
};

GetMonth 추가


위에서처럼 필요할 때마다 루틴을 추가해줘도 외부에서는 Month 만 보인다. 정말 편리한 키워드이지만, 안타깝게도 C++Builder 에서만 사용하는 확장 키워드이다. 그래서 property 가 아니라, __property 로 써야 한다. C++Builder 가 아닌 다른 컴파일러에서는 사용할 수 없다. 표준위원회에 제출은 되었으나, 언제 채택될 지 알 수 없다는 점이 아쉽다.