연산자재정의(operator overriding)
연산자는(operator) 궁극적으로 함수와(function) 같은, 자료형 혹은 객체를 다루기 위한 방법일(method) 뿐이다.
그래서 operator overloading 이란, (본질적으론 overriding 에 가깝다. overloading 은 실상 넌센스)
연산 기호를 함수이름과 동일시하는게 목적일 뿐이다.
오버로딩이란(과적 - 기존의 의미에 추가로 의미를 더하다) 단어를 연산자에 사용하기에는 무리가 있다.
1개 또는 2개의 피연산항을(operand) 갖는다와 같은 규칙밖에 이어지는 의미가 없고, 연산자 본연의 기능은 제거되니까 말이다.
(덧셈을 뺄셈으로 쓸 수도 있고, 덧셈을 단지 printf를 호출하는 함수로 만들 수도 있다)
추상화(abstraction)
사물의 본질을 간략히 추려내는것을 말한다.
프로그래밍 언어에서는 사물의 특징을 포괄할 자료형과 그것을 다루기 위한 적절한 연산을 선택(재사용) 또는 새롭게 정의하는 것을 말한다.
단어의 선택에서 의미부여가 이루어진다.
ex) 내가 만들 슈팅게임의 비행기 댓수를 5로 초기화 하겠다. (int 라는 자료형의 재사용과 의미부여의 예)
int player_airplane_count = 5;
여기서 남은 비행기 댓수는 chance 의 의미이기도 하다.
player_airplane_count++; 은 게임 속어로 보너스의 예가 되겠다.
어떤 단어가 개념을 포괄하기에 적절한지 고르는 작업은 혼동을 줄이기 위해, 문제를 정갈히 풀어나가기 위해 정말 중요한 작업이다.
만약 airplane 의 자료형을 PLAYER 객체로 재정의 한다면,
그에 필요한 연산들도 재정의 할수 있고, 격식을 갖추게 된다.
class PLAYER
{
private:
int chance;
public:
PLAYER() { chance = 5; }
void bonus()
{
chance++;
}
void die()
{
chance--;
if (chance < 1)
make_event(event_gameover);
}
};
격식을 갖추게 되었다는 말은, 실수할 여지가 줄고 의미가 명확해졌으며, 재사용 가능성이 증가하였음을 의미한다.
재사용 가능성이 증가되었다는 것은 한 편으로, 수정 필요시 수정할 곳이 한 곳으로 집중되었다는 것을 의미한다.
chance++; 을 곳곳에 코딩했다면, 수정 필요시 사용된 모든 곳에서 일일이 수정을 해야 하지만,
(이를테면 10대 이상 증가 못하게 하는 변경점 발생시)
bonus(); 를 곳곳에 코딩했다면, bonus() 의 정의부분만 수정하면 되는것이지.
캡슐화(encapsulation)
모든 자료는 자료의 존재만으로는 의미가 없다.
어떤 고고학자(사용자)가 도자기를 발견했다고 가정하자.
손잡이의 형태를 보고 이것이 어떤 목적을 위한 구조인지 고민할 것이다.
변수나 자료형만 선언해 놓고 알아서 해~ 하는건 문제 그 자체의 노출이지, 풀이나 해법이 아니다.
즉, 손잡이의 형태는 필연적으로 쥐는 법과 드는 법, 따르는 법, 걸어서 보관하는 법 등의
자료형의 구체적인 처리 방법과 뗄래야 뗄 수 없는 것이란거다.
처리방법이 명세되지 않은 도자기는 그냥 돌덩어리인거지.
하나의 개념적 덩어리 안에서 여러 메서드들이 다루게 될 재료(recipe) 에 대해 공유하는 부분 또한,
캡슐화가 가지는 팀웍과 우아함이다.
대중음식점이나, 고급레스토랑의 구조와 처리흐름을(work flow) 생각해보면 어떤 잇점들이 있는지 잘 알 수 있다.
주문을 받는 웨이터, 웨이트레스들과 요리사는 주문서를 공유하고, 요리의 결과물을 주고 받으며,
재료의 재고 상태를 공유한다.
필요시 웨이터들은 재료가 떨어졌음을 (메모리고갈 상태를) 고객에게 디버깅 메시지로 알려주기도 한다.
은닉화(hiding)
흔히 캡슐화와 혼용된다.
캡슐화의 과정에서, public 으로 공개할지, private 로 숨길지(며느리도 몰라),
protected 로 자손들에게만 알려줄지(며느리는 알아)를 서술하게 마련이기 때문이지만,
분명 개념은 캡슐화와 다르다.
고객이 식당에 와서 메뉴판을 보며 고르는 행위를 돕기 위해서
굳이 식당에서 들여오는 계란의 유통구조와 삶는 방법을 메뉴판에 열거할 필요는 없다.
알아서 나아질 것이 없다면 모르는게 약이다란 뜻이다.
너무 많은 인터페이스의 노출은 결정적으로 사용자 불편을 초래한다.
그래서 APPLE 의 미니멀리즘이 성공한거지. (ipod shuffle 같은 mp3 player 등이 좋은 예)
구글 검색에서 쓸데없는 검색결과들이 당신의 시간을 얼마나 좀먹는가?
심지어 인터넷에 당신에게 필요한 정보가 있을지라도, 불필요한 정보의 노출에 의해 필요한 내용을 평생 얻지 못할 수도 있다.
이렇듯 은닉화는 정말 중요한 개념이고, UI 나 인터페이스 설계에서 핵심적인 부분이다.
다형성(polymorphism)
동질이상.
큰 범주에서 개념이 같지만,
구체적으로는 다룰 대상, 또는 그 방법에 차이가 있는 방법(연산)을 같은 이름으로 부를 수 있게 하는 것이다.
착각하기 쉬운것은, 프로그래밍 언어에 있어서의 다형성이 일반적인 polymorphism의 개념과 달리,
비슷한 기능을 하는 서로 다른 함수들을 같은 이름으로 정의하는 것이라는 점. (매개변수의 타잎으로 각각 구분한다)
즉, 하나의 이름으로 다양한 자료형을 지원하는데 목적이 있다.
따라서 탬플릿과 목적 및 기능이 유사해 보이지만, 탬플릿은 보다 한정적이고 구체적이다.
다룰 자료형을 다양화하고 컴파일러로 하여금 실제 사용된 자료형을 다룰 메서드를 자동으로 서술하게 하는게 목적이지
다루는 방법을 다양화하지는 않기 때문이다.
요약하면, 다형성과 탬플릿은 자료형이나 객체를 다룰 연산자(매서드) 의 이름에 융통성을 주기 위한 것 뿐이다.
다형성은 같은 이름의 다양한 연산자(매서드)를 서술할 수 있고,
탬플릿은 같은 이름의 다양한 사용예에 대해 코딩량을 줄여준다.
상속성(inheritance)
추상화의 결과를 활용하여 구체적인 실례에 적용하는 것이다.
즉, 추상화를 통해 도출한 일반해로 부터 특수해를 위한 파라메터를 적용하고, 부족한 내용을 추가하는 것이라 볼 수 있다.
다른 말로, 추상화란것은 철학(프로그래밍은 고유의 notation을 사용하니 언어학 또는 수학)을 하는 것이고,
상속을 받았다는 것은 응용학문(이를테면 공학) 에 적용하는 것이다.
추상 객체와 상속을 받은 객체를 사용해 개체(instance)를 생성하고, 정의된 방법들을 이용해
요구사항을 구현(implement) 하는 것은 생산(production)에 해당하는 것이지.
위에서 예시한 bonus() 함수로의 가공의 예도 클래스 추상화와 상속성으로 확장해 이해할 수 있다.
즉, 함수오버로딩이란 자식 메서드의 진입시점에서 부모 메서드를 호출해주는 것이다.
생성자 함수 호출순서 역시 그러하다. 자식 생성자의 실행직전에 부모 생성자들을 재귀적으로 호출해 주는것이지.
여기서 중요한것은, 우리가 변수와 연산자를 (chance--) 하나의 함수로 싼 것과 마찬가지 잇점들이 객체화로 이어진다는거다.
이것이 랩핑(wrapping)즉 모듈화, 그리고 encapsulation의 장점이다.
클래싱(classing) - 뭐 좋은 한글 없냐?
목적한 결과물의 형태를 얻어내기 위해,
우리는 소조를 하든지(붙이기), 조각을 하게 된다. 거푸집이나 틀을 만들고 내용물을 부어넣는 주조(주물) 형태를 취하기도 한다.
(이를 위해 일시적으로 유동성과 점성을 갖도록 녹이는 작업을 하기도 하지)
원시 자료형(primitives)을 찰흙이나 지점토 처럼 유동성과 점성이 있는 성질로 정의할지,
대리석처럼 단단한(rigid) 성질로 정의할지,
일시적으로 점성을 갖거나, 강체(rigid object)끼리 접착할 수 있는(bonding) 형식으로 정의할지는
언어에서 지원하는 문법과, 개발자의 선택에 달린 문제다.
즉, 클래싱이란, 위에 언급한 추상객체와 상속객체를 어떤식으로 구성하고 결합할지를 결정하는 것이다.
부모객체 A를 상속받는다는 것은, 객체 A를 멤버로 선언하는 것과 아주 미세한 차이가 있을 뿐이다.
protected 접근권한을 허용할지와, override 같은 재정의를 사용할지 말지 정도랄까.
하지만 그때문에 hard binding 구조가 된다.
가능하면 상속을 자제하라는 이야기는 light binding을 유지해, 재사용성을 높이라는 이야기다.
요약하면, 접근권한을 바꿀 여지가 없거나, 가상함수들에 대한 override가 반드시 필요하다면 상속을 받아서 구현하란 이야기다.
드럽게 어렵네
감사합니다.
예제에서 gameover(); 라는 함수를 호출하는 형태가 아닌 이벤트를 만드는 형태로 기술한 것은, light binding 의 장점을 가져가기 위한 것이다.
만약 비행기 객체 안에 게임종료를 처리할 구체적인 코드가 들어가게 되면, 다른 게임을 만들때 그대로 사용할 가능성이 거의 없는 코드라고 볼 수 있다.
아주 사소한 실수들과 참조의 종속성들이 객체의 재사용성을 소멸시켜버린다.
경제성을 위해 내부 결속력을 강화하고, 재사용성을 위해 위해 외부 결속력을 약화시켜라.
종속성이 너무 강하면 안된다는 말이군요. 감사합니다.
event driven 이 절차구조에 비해 갖게 되는 비절차적 잇점은, light binding 의 장점을 얻는것과 비슷하다고 말 할 수 있다는 것이다.
event, message, interrupt, signal 에 대해 과거에 쓴 글이 있지만, (지웠나 몰러) IPC 와 같은 내부 통신 기술을 활용한 구조는 재사용성을 돕는다는 말이지.
만약 윈도우즈 운영체제에서 메세지가 없이 바로 바로 함수가 호출이 되었다면, 프로세스별 가상메모리 지원은 꿈도 꿀수 없고, 커널은 엄청난 량의 메모리를 사용하게 되었을 것이다. (실제 완전히 isolation되지 않았기에 2G 나 되는 메모리를 쳐먹고 있다)
개추
클래싱은 적당한 한국말이 없네..더 정확히 말하면 한자가 없네. 순수 한글은 학문에 사용하기 어려움.
그러게~
개추
어엌ㅋㅋㅋㅋ믖용>_<ㅋ