Smalltalk80LanguageImplementationKor:Chapter 01

From 흡혈양파의 번역工房
Jump to navigation Jump to search
1장 객체와 메시지

객체와 메시지

객체는 Smalltalk-80 소프트웨어 시스템의 구성요소에 해당된다. 객체의 예는 다음과 같다.

  • numbers
  • character strings(문자열)
  • queues
  • dictionaries
  • rectangles
  • file directories
  • text editors
  • programs
  • compilers
  • computational processes
  • financial histories(재정내역)
  • views of information(정보보기)


객체는 private 메모리와 연산 집합으로 구성된다. 객체 연산의 특성은 그것이 표현하는 구성요소 타입에 따라 좌우된다. 숫자를 표현하는 객체들은 산술 연산을 계산한다. 데이터 구조체를 나타내는 객체들은 정보를 보관하고 검색한다. 또 위치와 면적을 나타내는 객체들은 다른 위치와 면적에 관한 질문에 답한다.


메시지는 객체가 자신의 작업중 하나를 실행하기 위한 요청이다. 메시지는 어떤 연산이 바람직한지를 명시할 뿐, 연산이 어떻게 실행되어야 하는지를 명시하지는 않는다. 메시지를 수신하는 객체인 수신자(receiver)는 요청 받은 연산을 어떻게 실행할 것인지를 결정한다. 가령 addition(덧셈) 연산은 숫자를 표현하는 객체에게 메시지를 전송함으로써 실행된다. 메시지는 바람직한 연산이 addition 임을 명시하며, 수신자에게 어떤 숫자가 추가되어야 하는지도 명시한다. 메시지는 addition 이 어떻게 실행될 것인지는 명시하지 않는다. addition 을 어떻게 실현할 것인지는 수신자가 선택한다. Computing(계산)은 메시지를 전송함으로써 균일하게 호출할 수 있는 객체의 고유 기능으로 볼 수 있다.


객체가 응답할 수 있는 메시지 집합을 나머지 시스템 과의 인터페이스라고 부른다. 객체와 상호작용할 수 있는 유일한 방법은 인터페이스를 이용하는 것이다. 객체의 중요한 특성으로서, 객체의 private 메모리는 객체 고유의 연산에 의해서만 조작할 수 있다는 점을 들 수 있다. 메시지의 중요한 특성은, 메시지가 객체의 연산을 호출하는 유일한 방법이라는 것이다. 이러한 특성들은 한 객체의 구현이 다른 객체의 내부적 세부사항에 의존할 수 없으며, 그들이 응답하는 메시지에만 의존하도록 보장한다.


메시지는 바람직한 연산 타입을 명시하지만 연산이 어떻게 실현되어야 하는지는 명시하지 않기 때문에 시스템의 모듈화를 보장한다. 예를 들어, Smalltalk-80 시스템에는 몇 가지 수치 값 표현들이 있다. Fractions(분수), small integers, large integers, 그리고 floating point numbers(부동소수점)는 서로 다르게 표현된다. 이 값들은 모두 동일한 메시지를 이해하면서 다른 숫자와의 총계 계산을 요청하지만 각 표현은 총계를 계산하는 다른 방식을 암시한다. 숫자 또는 다른 객체와 상호작용하기 위해서는 객체가 어떤 메시지에 응답하는지만 알아도 충분하며, 그것이 어떻게 표현될지는 몰라도 된다.


다른 프로그래밍 환경들도 객체와 메시지를 사용해 모듈식 디자인을 가능하게 한다. 예를 들어, Simula 는 이들을 이용해 시뮬레이션을 설명하며, Hydra는 분산 시스템에서 운영체제 기능을 설명하기 위해 사용한다. Smalltalk-80 시스템에서 객체와 메시지는 전체적인 프로그래밍 환경을 구현하는 데에 사용된다. 객체와 메시지를 이해하면 전체 시스템에 접근할 수 있게 된다.


프로그래밍에서 흔히 사용되는 데이터 구조체의 예로 dictionary 를 들 수 있는데, 이 클래스는 이름과 값을 조합시킨다. Smalltalk-80 시스템에서 dictionary 는 두 개의 연산, 즉 이름을 새로운 값과 조합시키는 연산과 특정 이름과 마지막으로 조합된 값을 찾아내는 연산을 수행할 수 있는 객체로 표현된다. dictionary 를 사용하는 프로그래머는 이 두 연산을 메시지로 명시하는 방법을 알아야만 한다. Dictionary 객체는 "Brett 이란 이름과 값 3 을 연관시켜라" 또는 "Dave란 이름과 연관된 값은 무엇인가?" 식의 요청을 하는 메시지를 이해해야 한다. 모든 것은 객체이기 때문에 Brett이나 Dave와 같은 이름과 3이나 30과 같은 값 또한 객체로 표현된다. 호기심이 많은 프로그래머라면 dictionary 에서 연관(association)이 어떻게 표현되는지 궁금하겠지만, 이러한 내부적 구현 정보는 dictionary 를 성공적으로 사용하는 데에 불필요하다. dictionary 의 구현에 대한 지식은 dictionary 객체 자체의 정의를 작업하는 프로그래머에게만 관심의 대상이 된다.


Smalltalk-80 프로그램을 설계하는 경우에서 중요한 부분은 어떤 유형의 객체가 설명되어야 하며, 어떤 메시지명이 이러한 객체들 사이의 상호작용에 대해 유용한 용어를 제공하는지 결정하는 것이다. 프로그래머가 객체에 보낼 수 있는 메시지를 지정할 때마다 언어가 설계된다. 객체의 적절한 선택은 물론이고, 객체의 목적과 조작되어야 하는 정보의 세분화(granularity of information)에 따라 좌우된다. 예를 들어, 다양한 놀이기구에서 대기열에 관한 데이터를 수집하려는 목적으로 놀이공원의 시뮬레이션을 작성한다면 놀이기구를 나타내는 물건, 놀이기구를 제어하는 직원, 대기줄, 공원을 방문하는 사람을 표현하는 것이 유용할 것이다. 시뮬레이션의 목적이 공원 내의 식품 소비량까지 모니터링하는 것을 포함한다면, 이러한 소모 자원을 가리키는 물체가 필요하다. 만약 공원 내에서 교환된 돈의 양이 모니터링 되어야 한다면, 놀이 기구 가격에 대한 세부 사항도 제시되어야 한다.


Smalltalk-80 애플리케이션을 설계할때 객체의 선택은 가장 중요한 단계가 된다. 객체를 선택하는데에 있어 정석적인 "올바른 방법" 은 없다. 모든 설계과정처럼 경험에 의해 습득된 기술이다. 응용프로그램을 확장하거나 객체를 다른 용도로 사용하기 위해 다양한 선택사항이 제공됩니다. 숙련된 Smalltalk-80 프로그래머는 객체에 대해 구문적으로 완전한 함수 집합이 지정되면, 응용프로그램을 위해 생성된 객체가 다른 응용프로그램에도 더 유용할 수 있다는걸 염두에 둔다. 예를들어 조합의 추가뿐 아니라 제거가 가능한 dictionary 는 주로 추가만 가능한 버전보다 쓸모가 있다.


클래스와 인스턴스

클래스는 모두 동일한 유형의 시스템 구성요소를 나타내는 객체 집합의 구현을 나타낸다. 클래스가 설명하는 각각의 객체들을 객체의 인스턴스라고 부른다. 클래스는 그 인스턴스의 private 메모리 형태를 나타내며, 객체가 어떻게 연산을 실행해야 하는지를 나타낸다. 예를 들어, 직사각형 영역을 표현하는 객체의 구현을 나타내는 시스템 클래스가 있다. 이 클래스는 각 인스턴스들이 그들의 면적 위치를 어떻게 기억하는지, 직사각형 영역이 실행하는 연산을 인스턴스가 어떻게 실행하는지를 나타낸다. Smalltalk-80 시스템 내의 모든 객체는 클래스의 인스턴스에 해당한다. 고유의 시스템 구성요소를 나타내는 객체조차 클래스의 단일 인스턴스로 구현된다. Smalltalk-80 시스템에서 프로그래밍은 클래스를 생성하고, 클래스의 인스턴스를 생성하며, 이러한 객체들 사이의 메시지 교환 순서를 지정등으로 구성된다.


클래스의 인스턴스는 public 속성과 private 속성이 서로 비슷하다. 객체의 public 속성은 그 인터페이스를 구성하는 메시지들이다. 클래스의 모든 인스턴스는 동일한 유형의 구성요소를 표현하기 때문에 동일한 메시지 인터페이스를 가진다. 객체의 private 속성에는 private 메모리를 구성하는 인스턴스 변수의 집합과, 객체의 연산을 어떻게 실행하는지 설명하는 메서드 집합이 해당된다. 인스턴스 변수와 메서드를 다른 객체에서 직접 이용할 수는 없다. 클래스의 인스턴스들은 모두 동일한 메서드 집합을 이용하여 연산을 서술한다. 예를 들어, 직사각형 도형을 나타내는 인스턴스들은 전부 동일한 메시지 집합에 응답하며, 응답 방식을 결정하는 데에 모두 동일한 메서드를 사용한다. 각 인스턴스에는 고유의 인스턴스 변수 세트가 있지만, 일반적으로 인스턴스 변수의 개수는 모두 동일하다. 예를 들어, 직사각형을 나타내는 인스턴스들은 모두 두 개의 인스턴스 변수를 가진다.


각 클래스에는 인스턴스가 나타내는 구성요소 유형을 설명하는 이름이 붙여진다. 클래스명은 프로그래밍 언어의 일부이기 때문에 특수 글꼴로 표시된다. Smalltalk-80 표현식을 나타내는 텍스트에는 모두 동일한 글꼴이 사용된다. 인스턴스가 문자 시퀀스를 표현하는 클래스를 String 이라고 부른다. 인스턴스가 공간적 위치를 나타내는 클래스는 Point 로 불린다. 직사각형 영역을 나타내는 클래스는 Rectangle 이라 부른다. 계산 처리를 나타내는 인스턴스를 포함한 클래스는 Process 라고 부른다.


객체의 private 메모리 안의 각 인스턴스 변수는 value 라고 불리는 하나의 객체를 참조한다. Rectangle 의 두 인스턴스 변수값은, 직사각형 영역의 반대편 모서리들을 가리키는 Point의 인스턴스들이다. Rectangles 에 두 개의 인스턴스 변수가 있다거나, 인스턴스 변수가 Points 를 참조한다는 사실은 각 Rectangle 밖에서는 이용할 수 없는, 엄격한 내부 정보에 해당된다.


클래스 안의 각 메서드는 특정 타입의 메시지가 요청한 연산을 어떻게 실행하는지 알려준다. 해당 타입의 메시지가 클래스의 어떤 인스턴스에게라도 전송되면 메서드가 실행된다. 모든 Rectangles 가 사용하는 메서드는 반대쪽 모서리를 나타내는 두 개의 Points 와 관련해 그 연산을 어떻게 실행할 것인지를 서술한다. 예를 들어, 한 메시지가 Rectangle 에게 중심 위치를 묻는다. 그에 상응하는 메서드는 반대편 모서리 중간에 있는 점을 찾아 중심을 계산하는 방법을 알려준다.


클래스에는 인스턴스가 실행할 수 있는 각 연산 유형에 따른 메서드를 포함되어 있다. 메서드는 객체의 private 메모리, 그리고 전송되어야 할 다른 메시지들에 대한 변경내용을 명시한다. 메서드는 그 외에도 호출하는 메시지의 값으로 반환되어야 하는 객체를 명시하기도 한다. 객체의 메서드는 객체 고유의 인스턴스 변수로 접근할 수 있지만 다른 객체의 인스턴스 변수로는 접근할 수 없다. 예를 들어, Rectangle 이 자신의 중심을 계산하기 위해 사용하는 메서드는 해당 인스턴스 변수가 참조하는 두 개의 Point 로의 접근성을 갖지만, 그러한 Points 의 인스턴스 변수로는 접근할 수 없다. 메서드는 Points 에게 필요한 계산의 실행을 요청하는 메시지를 지정한다.


Smalltalk-80 에서 메서드 하위집합의 일부는 Smalltalk-80 프로그래밍 언어에 표시되지 않는다. 이들은 primitive 메서드라고 부른다. primitive 메서드는 가상 머신에 빌드되며, Smalltalk-80 프로그래머가 변경할 수 없다. 이들은 다른 메서드와 정확히 같은 방식으로 메서드를 이용해 호출된다. primitive 메서드는 기본이 되는 하드웨어와 가상 머신 구조(structures)로의 접근을 허용한다. 예를 들어, Integer 의 인스턴스들은 +(plus) 메시지에 응답하기 위해 primitive 메서드를 사용한다. 그 외에도 primitive 메서드는 디스크와 단말기(terminal) 상호작용을 실행한다.

예제 애플리케이션

예제는 프로그래밍 언어와 환경을 설명하기 위한 중요한 부분이다. 본문에 사용된 예제의 대다수는 표준 Smalltalk-80 시스템에서 발견할 수 있는 예제들이다. 그 외 예제들은 기능을 향상시키기 위해 시스템에 추가될 수 있는 클래스로부터 얻어낸 것이다. 본 서적의 제 1부는 개인, 가정, 단체 또는 소규모 사업을 대상으로 한 간단한 재정 내역(financial history)을 유지하기 위해 시스템에 추가할 수 있는 애플리케이션에서 예제를 가져왔다. 전체 응용프로그램을 사용해서 금융거래에 대한 정보를 입력하고 해당 정보를 볼 수 있는 보기를 표시할 수 있다. 그림 1.1은 Smalltalk-80 디스플레이 화면에 표시될 재정 내역의 모습이다. View 의 상단에 위치한 두 개의 부분은 다양한 용도로 사용된 자금의 금액을 표시하는 두 개의 View 다. 그 아래의 View 는 거래가 이루어질 때 시간의 흐름에 따라 수중의 현금이 어떻게 변하는지 보여준다.


그림의 아래쪽에는 사용자가 새로운 지출과 수익을 기록에 추가하기 위해 입력할 수 있는 두 개의 영역이 존재한다. 새로운 정보가 추가되면 세 개의 View 가 자동으로 갱신된다. 그림 1.2 에는 식품에 대한 새로운 지출이 추가된 모습이다.


이 응용프로그램은 시스템에 몇가지 클래스를 추가해야 한다. 이러한 새 클래스들은 기본이 되는 재정 내역 정보뿐 아니라 여러 가지 유형의 View 를 서술하기도 한다. 재정 내역을 실제로 기록하는 클래스는 FinancialHistory 라고 부르며, 다음 네 개의 장에서 예제로 사용될 것이다. 이러한 응용프로그램 예제는 시스템에 이미 존재하는 몇 가지 클래스를 사용할 것이며, numbers 를 사용해 금액을 표현하고, 지출의 이유와 수익의 출처는 String 을 사용해 표현할 것이다.


FinancialHistory 는 기능과 구현을 설명하기 쉽기 때문에, 이를 이용해 Smalltalk-80 프로그래밍 언어의 기본 개념을 소개할 것이다. 클래스의 기능은 메시지 인터페이스를 통해 이용 가능한 연산을 열거함으로써 명시할 수 있다. FinancialHistory 는 6가지의 연산을 제공한다.

  1. 이용할 수 있는 초기 금액이 확정된 새로운 재정 내역 객체를 생성.
  2. 특정 금액이 어떤 용도로 사용되었음을 기억.
  3. 특정 금액이 어떤 출처로부터 들어왔음을 기억.
  4. 금액을 얼마나 이용할 수 있는지 알아내기.
  5. 어떤 용도에 얼마나 소비했는지 알아내기.
  6. 어떤 출처로부터 얼마나 수신하였는지 알아내기.


그림 1-1

그림 1-2


이러한 연산들의 구현은 본 서적의 표지 커버 안에 표시된 클래스 설명(class description)에 명시되어 있다. 클래스 설명의 구성은 제 3, 4, 5장에서 설명할 것이다.

시스템 클래스

Smalltalk-80 시스템은 프로그래밍 언어와 환경의 표준 기능, 즉 산술, 데이터 구조체, 제어 구조체, 입/출력 기능을 제공하는 클래스 집합을 포함하고 있다. 이러한 클래스들의 기능은 본 서적의 제 2부에서 상세히 설명할 것이다. 그림 1.3은 제 2부에 제시한 시스템 클래스의 다이어그램이다. 관련 클래스 그룹의 주위에 직선을 그렸으며, 그룹은 클래스 명세를 찾을 수 있는 장(chapter)을 나타내도록 라벨로 붙였다.

그림 1-3


산술(Arithmetic)

Smalltalk-80 시스템은 실수와 유리수를 모두 표현하는 객체를 포함한다. 실수는 약 6자릿수의 정확도로 표현할 수 있다. 252428 미만인 절대값의 정수는 정확히 표현 가능하다. 유리수는 이러한 정수를 이용해 나타낼 수 있다. 선형적 크기(예: 일자와 시간)와 무작위 수 발생기를 나타내기 위한 클래스들도 있다.


데이터 구조체

Smalltalk-80 시스템 안의 대부분의 객체는 어떤 유형의 데이터 구조체로 기능한다. 하지만 대부분의 객체들은 다른 기능도 가지고 있지만, 그에 비해 다소 순수한 데이터 구조체만을 표현하는 클래스 집합도 있다. 이러한 클래스들은 여러 타입의 컬렉션을 표현한다. 일부 컬렉션의 요소(element)들은 정렬되지 않으며 나머지는 정렬가능하다. 정렬되지 않은 요소가 있는 컬렉션에는 중복 요소를 허용하는 백(bag)과 중복을 허용하지 않는 세트(set)가 있다. 또 객체의 쌍을 조합시키는 dictionary 도 존재한다. 정렬된 요소들 중에서 일부는 요소가 추가될 때 외부에서 순서를 지정할 수 있으며, 요소의 속성을 기반으로 해서 스스로의 정렬을 결정하는 요소들도 있다. 문자열과 배열에 공통된 데이터 구조체는 연관 행위(색인과 요소를 연관시킴)와 외부 정렬(색인의 내재적 정렬에 상응)을 가진 클래스에 의해 제공된다.


제어 구조체

Smalltalk-80 시스템은 대부분의 프로그래밍 언어에서 발견되는 표준 제어 구조체를 구현하는 메시지와 객체를 포함하고 있다. 이들은 Algol 의 if-then-else 문과 비슷한 조건 선택 및 while 또는 until 문과 비슷한 조건 반복을 제공한다. 스케줄링과 동기식 상호작용에 대해 독립된 처리 및 메커니즘을 표현하는 객체들 역시 제공된다. 이러한 제어 구조를 지원하기 위해 두 개의 클래스가 제공된다. Booleans 는 두 개의 진실(truth) 값을 나타내고, 블록은 액션의 순서를 나타낸다. Boolean 과 블록을 이용해 새로운 유형의 제어 구조체를 생성할 수 있다.


프로그래밍 환경

Smalltalk-80 시스템에는 프로그래밍 과정에 도움이 되는 클래스가 몇 개 있다. 이들은 메서드의 컴파일된 (머신이 실행할 수 있는) 형태와 소스(인간이 읽을 수 있는) 형태를 표현하는 구분된 클래스들이다. 파서, 컴파일러, 역컴파일러를 나타내는 객체들은 그들을 사용하는 객체 (클래스의 인스턴스들)와 메서드를 연결한다.


클래스와 메서드에 대한 조직화된 구조체를 나타내는 객체는 프로그래머가 시스템을 추적하도록 도우며, 소프트웨어 수정 내역을 표현하는 객체들은 다른 프로그래머들의 노력과 인터페이스를 돕는다. 심지어 메서드의 실행 상태를 객체가 표현하기도 한다. 이러한 객체들을 컨텍스트(context)라고 부르며, 다른 시스템의 활성화 기록 또는 스택 프레임과 비슷하다고 볼 수 있다.


살펴보기(Viewing)와 상호작용(Interacting)

Smalltalk-80 시스템은 정보를 살펴보고 편집하는 데에 사용할 수 있는 객체의 클래스를 포함하고 있다. 그래픽한 뷰를 표현하는 데에 도움이 되는 클래스는 점, 선, 직사각형, 원호를 표현한다. Smalltalk-80 시스템은 비트맵 디스플레이를 지향하기 때문에 비트맵 이미지를 표현하고 조작하는 클래스가 존재한다. 문자 글꼴, 텍스트, 커서를 대상으로 한 좀 더 구체적인 비트맵 이미지의 사용을 표현 및 조작하기 위한 클래스도 존재한다.


이러한 그래픽 객체로부터 직사각형 창, 명령 메뉴, 내용 선택을 나타내는 다른 객체들도 만들어진다. 입력 장치에 대한 사용자의 액션을 나타내는 객체와, 이러한 동작들이 현재 보고 있는 정보에 어떻게 연관되는지를 나타내는 객체도 있다. 이러한 구성요소로부터 생성된 편집 메커니즘과 특정 보기(viewing)를 표현하는 클래스들은 클래스, 컨텍스트, 그리고 텍스트와 그래픽을 포함하는 문서에 대한 뷰(view)를 제공한다. 클래스의 뷰는 시스템 내 소프트웨어와 상호작용하기 위한 기본적인 메커니즘을 제공한다. Smalltalk-80 과 에디터는 별도의 서적에서 소개한다.


통신

Smalltalk-80 시스템은 외부 매체와의 통신을 허용한다. 표준 외부 매체는 디스크 파일 시스템이 해당한다. 객체는 디렉터리뿐만 아니라 개별 파일을 표현한다. 통신 네트워크의 연결을 이용할 수 있다면 객체를 통해서도 접근할 수 있다.

용어 정리

객체(object) 일부 private 메모리와 연산 집합으로 표현되는 Smalltalk-80 시스템의 구성요소.
메시지(message) 객체가 그 연산 중 하나를 실행하라는 요청.
수신자(receiver) 메시지가 전송되는 대상 객체.
인터페이스(interface) 객체가 반응할 수 있는 메시지.
클래스(class) 유사한 객체 그룹에 대한 설명.
인스턴스(instance) 클래스가 설명하는 객체들 중 하나.
인스턴스 변수(instance variable) 객체의 private 메모리의 부분.
메서드(method) 객체의 연산들 중 하나를 어떻게 실행할 것인지에 대한 설명.
primitive 메서드(primitive method) Smalltalk-80 가상 머신에서 직접 실행되는 연산.
FinancialHistory 본 서적에서 예제로 사용된 클래스명.
시스템클래스(system classes) Smalltalk-80 시스템에 따라오는 클래스 집합.

Notes