Smalltalk80LanguageImplementationKor:Chapter 05

From 흡혈양파의 번역工房
Jump to navigation Jump to search
제 5 장 메타클래스

메타클래스(Metaclasses)

모든 Smalltalk-80 시스템 구성요소는 객체로 표현되고 모든 객체는 클래스의 인스턴스이므로 클래스 자체는 클래스의 인스턴스로 표현되어야 한다. 클래스를 인스턴스로 가진 클래스를 메타클래스라고 부른다. 이번 장에서는 메타클래스의 특별한 속성을 설명하겠다. 예를 통해 메타클래스가 인스턴스 생성과 일반적인 클래스 문의를 어떻게 지원하는지 보이고자 한다.


Smalltalk 시스템의 초기 버전들의 경우 Class라는 하나의 메타클래스만 존재했다. 이는 그림 5.1에 설명된 클래스 조직에 해당한다. 제 4장에서 사용되었듯이 박스는 클래스를 나타내고 원은 그것이 포함된 클래스의 인스턴스를 나타낸다. 박스에는 그것이 나타내는 클래스명의 이름을 표기하였다. Class라는 이름의 박스에는 그림 속 각 상자마다 하나씩 원을 그렸다.

그림 5-1


이 접근법은 모든 클래스의 메시지 프로토콜이 동일할 수밖에 없다는 한계가 있는데, 이는 한 장소에서 명시되기 때문이다. 특히 새로운 인스턴스를 생성하는 데에 사용되는 메시지는 모든 클래스에 동일하고 특별한 초기화 요구조건을 고려할 수 없었기 때문이다. 단일 메타클래스를 이용하면 모든 클래스는 인스턴스 변수가 모두 nil을 참조하는 인스턴스를 리턴함으로써 new 또는 new:로 응답한다. 대부분의 객체의 경우 nil은 합당한 인스턴스 변수 값이 아니므로 새로운 인스턴스는 다른 메시지를 전송하여 초기화되어야 한다. 프로그래머는 new 또는 new: 가 전송될 때마다 새로운 객체로 다른 메시지가 전송되어 적절하게 초기화될 수 있도록 확보해야만 한다. 이러한 유형의 초기화에 해당하는 예는 제 4장, SmallDictionary와 FinancialHistory에서 소개한 바 있다.


Smalltalk-80 시스템은 각 클래스를 고유의 메타클래스의 인스턴스로 만들어서 모든 메타클래스가 동일한 메시지 프로토콜을 가져야 한다는 제약을 없앤다. 새로운 클래스가 생성될 때마다 자동으로 새로운 메타클래스가 생성된다. 메타클래스는 그들의 인스턴스가 사용하는 메서드를 포함하기 때문에 다른 클래스들과 유사하다. 메타클래스가 다른 클래스와 다른 점은, 그 자체가 메타클래스의 인스턴스가 될 수 없다는 점이다. 대신 Metaclass라는 클래스의 인스턴스가 된다. 또 메타클래스는 클래스명을 갖고 있지 않다. 메타클래스는 그 인스턴스에게 class라는 단항 메시지를 전송함으로써 접근이 가능하다. 가령 Rectangle의 메타클래스는 Rectangle class 표현식을 이용해 참조할 수 있다.


메타클래스의 메시지는 일반적으로 인스턴스의 생성과 초기화, 클래스 변수의 초기화를 지원한다.


인스턴스(Instances)의 초기화

각 클래스는 적절하게 초기화된 새로운 인스턴스를 요청하는 메시지에 응답한다. 다중 메타클래스가 필요한 이유는 초기화 메시지가 다른 클래스에 사용되는 것과 다르기 때문이다. 가령, Time은 now라는 메시지에 대한 응답으로 새로운 인스턴스를 생성하고 Date는 today라는 메시지에 대한 응답으로 새로운 인스턴스를 생성한다는 사실은 이미 살펴본 바 있다.

Time now
Date today


이러한 메시지들은 인스턴스가 2차원 위치를 나타내는 클래스 Point에는 아무 의미가 없다. Point는 좌표를 명시하는 두 개의 인자와 x:y:를 선택자로 하는 메시지에 대한 응답으로 새로운 인스턴스를 생성한다. 그리고 이 메시지는 Time이나 Date에게는 아무런 의미가 없다.

Point x: 100 y: 150


Rectangle 클래스는 새로운 인스턴스를 생성하는 여러 개의 메시지를 이해한다. orgin:corner: 선택자를 가진 메시지는 상단 좌측 좌표와 하단 우측 좌표를 인자로 표현하는 Points를 취한다.

Rectangle
    orgin: (Point x: 50 y: 50)
    corner: (Point x: 250 y: 300)


origin:extent: 선택자로 된 메시지는 상단 좌측 모서리, 그리고 너비와 높이를 나타내는 Point를 인자로 취한다. 아래 표현식을 이용하더라도 동일한 직사각형을 생성할 수 있다.

Rectangle
    orgin: (Point x: 50 y: 50)
    extent: (Point x: 200 y: 250)


Smalltalk-80 시스템에서 Class는 모든 메타클래스에 대한 추상 슈퍼클래스다. Class는 클래스의 일반적인 특성을 설명한다. 각 메타클래스는 그것의 단일 인스턴스에 특정적인 행위를 추가한다. 메타클래스는 위에서 언급한 Date, Time, Point, Rectangle의 것과 같은 새로운 인스턴스 생성 메시지를 추가할 수도 있고, 아니면 기본적인 초기화를 실행하기 위해 기본 new와 new: 메시지를 재정의할 수도 있다.


지금까지 설명한 시스템 내 클래스와 인스턴스의 구조는 그림 5.2에 설명되어 있다.

그림 5-2


이 그림에서 우리는 Object, Metaclass, Class 클래스와 각각에 대한 메타클래스를 표현한다. Metaclass라는 박스 내 원은 각 메타클래스를 표시한다. Class라는 박스 내에 박스는 Class의 서브클래스를 나타낸다. Metaclass라는 박스 내에 각 원마다 그러한 박스가 하나씩 해당한다. 이러한 박스 각각은 그 인스턴스를 나타내는 원을 포함하는데, 이러한 인스턴스들은 Object 또는 Object의 서브클래스 중 하나를 참조하지만 메타클래스를 참조하지는 않는다.


메타클래스 예제

클래스와 그 메타클래스 간에는 일대일 대응관계가 존재하므로 그 설명은 함께 표시된다. 구현 설명에는 메타클래스에 의해 추가된 메서드를 표시하는 "class methods(클래스 메서드)" 라는 부분이 포함되어 있다. 메타클래스에 대한 프로토콜은 항상 단일 인스턴스의 구현 설명의 클래스 메서드 부분에서 찾을 수 있다. 이러한 방식을 통해 클래스(클래스 메서드)로 전송된 메시지와 클래스의 인스턴스(인스턴스 메서드)로 전송된 메시지는 전체적인 구현 설명의 일부로 함께 열거된다.


아래와 같이 FinancialHistory에 대한 구현 설명의 새로운 버전에는 클래스 메서드가 포함된다.

클래스명 FinancialHistory
슈퍼클래스 Object
인스턴스 변수명 cashOnHand
incomes
expenditures
클래스 메서드
instance creation
    initialBalance: amount
         super new setInitialBalance: amount
    new
         super new setInitialBalance: 0
인스턴스 메서드
transaction recording
    receive: amount from: source
        incomes at: source
            put: (self totalReceivedFrom: source) + amount.
        cashOnHand   cashOnHand + amount
    spend: amount for: reason
        expenditures at: reason
            put: (self totalSpentFor: reason) + amount.
        cashOnHand   cashOnHand - amount

inquiries
    cashOnHand
         cashOnHand
    totalReceivedFrom: source
        (incomes includesKey: source)
            ifTrue:[ incomes at: source]
            ifFalse: [ 0]
    totalSpentFor: reason
        (expenditures includesKey: reason)
            ifTrue:[ expenditures at: reason]
            ifFalse:[ 0]

private
    setInitialBalance: amount
        cashOnHand   amount.
        incomes   Dictionary new.
        expenditures   Dictionary new


구현 설명에 세 가지 사항이 변경되었다.

  1. instance creation이라는 클래스 메서드의 범주 하나가 추가되었다. 범주는 initialBalance:와 new에 대한 메서드를 포함한다. 관습상 instance creation 범주는 새로운 인스턴스를 리턴하는 클래스 메서드에 사용된다.
  2. initialization이라는 인스턴스 메서드의 범주가 삭제되었다. 이는 initialBalance: 에 대한 메서드를 포함하였다.
  3. private이라는 인스턴스 메서드의 범주가 추가되었다. 범주는 setInitialBalance: 에 대한 하나의 메서드를 포함하는데, 이 메서드는 initialBalance: 에서 삭제된 메서드에 위치했던 것과 동일한 표현식을 포함한다.


위의 예제는 메타클래스가 어떻게 초기화된 인스턴스를 생성하는지를 보여준다. initialBalance: 와 new에 대한 인스턴스 생성 메서드는 새로운 인스턴스의 인스턴스 변수들로 (cashOnHand, incomes, expenses) 직접 접근하지 못한다. 이는 메서드가 새 인스턴스의 클래스에 속하지 않고 클래스의 클래스에 속하기 때문이다. 따라서 인스턴스 생성 메서드는 먼저 비초기화된 인스턴스를 생성한 후 초기화 메시지 setInitialBalance: 를 새로운 인스턴스로 전송한다. 해당 메시지에 대한 메서드는 FinancialHistory의 구현 설명의 인스턴스 메서드 부분에서 발견되며, 인스턴스 변수로 적절한 값을 할당할 수 있다. 초기화 메시지는 FinancialHistory의 외부 프로토콜의 일부로 간주되지 않으므로 private으로 범주화된다. 이 메시지는 주로 클래스 메서드에 의해 한 번만 전송된다.


기존의 초기화 메시지 initialBalance: 는 삭제되는데, FinancialHistory를 적절하게 생성하기 위해서는

FinancialHistory initialBalance: 350


위와 같은 표현식이 아니라 아래와 같은 표현식을 사용해야 하기 때문이다.

FinancialHistory new initialBalance: 350


사실상 첫 번째 표현식은 FinancialHistory의 인스턴스가 더 이상 initialBalance: 에 응답하는 것으로 설명되지 않기 때문에 지금쯤 오류를 생성할 것이다. 우리는 인스턴스 메서드 initialBalance: 를 유지하고 그곳에서 호출하도록 initialBalance: 에 대한 클래스 메서드를 구현할 수도 있지만, 구현 설명의 가독성을 향상시키기 위해 인스턴스와 클래스 메서드에 동일한 선택자를 사용하지 않고자 했다. 하지만 동일한 선택자가 사용되었다면 모호함은 없을 것이다.


메타클래스 상속(Metaclass Inheritance)

다른 여느 클래스와 마찬가지로 메타클래스는 슈퍼클래스로부터 상속된다. 메타클래스의 상속을 구성하는 가장 간단한 방법은 각 메타클래스를 Class의 서브클래스로 만드는 방법이다. 이러한 구조는 그림 5.2에 소개되어 있다. Class는 클래스의 일반적인 특성을 설명한다. 각 메타클래스는 인스턴스 특정적인 행위를 추가한다. 메타클래스는 새로운 인스턴스 생성 메시지를 추가하거나 기본적인 new와 new: 메시지를 재정의하여 일부 기본 초기화를 실행할 수 있다.


메타클래스가 Smalltalk-80 시스템으로 추가될 때 클래스 구성에 추가로 한 가지 단계가 더 실행되었다. 메타클래스 서브클래스 계층구조는 그 인스턴스에 해당하는 클래스들의 서브클래스 계층구조에 비슷하도록 강요된다. 따라서 DeductibleHistory가 FinancialHistory의 서브클래스라면 DeductibleHistory의 메타클래스는 FinancialHistory의 메타클래스의 서브클래스여야만 한다. 메타클래스에는 주로 하나의 인스턴스만 존재한다.


ClassDescription이라는 추상 클래스는 클래스와 그 인스턴스를 설명하기 위해 제공된다. Class와 Metaclass는 ClassDescription의 서브클래스들이다. 모든 객체의 슈퍼클래스 사슬은 Object에서 끝나고 Object는 슈퍼클래스를 갖고 있지 않으므로 Object의 메타클래스의 슈퍼클래스는 Class가 된다. Class에서 메타클래스들은 인스턴스를 생성하기 위한 프로토콜을 제공하는 메시지들을 상속받는다 (그림 5.3).


Class에서 시작된 슈퍼클래스 사슬은 마지막으로 Object로 연결된다. Object class라는 이름으로 된 박스의 계층구조는 Object라는 박스 안에 존재하는 박스들의 계층구조와 동일함을 주목하며, 이는 서로 닮은 계층구조를 증명한다. Metaclass와 그 메타클래스의 관계를 포함해 시스템에서 이러한 부분에 대한 전체 설명은 제 16장에 제공된다.

그림 5-3


메타클래스 상속구조의 한 가지 예로, FinancialHistory class 내에 initialBalance: 의 구현을 고려해보자.

initialBalance: amount
     super new setInitialBalance: amount


해당 메서드는 super new 표현식을 평가함으로써 새로운 인스턴스를 생성하고, 해당 클래스에서 발견되는 클래스 메서드가 아니라 슈퍼클래스의 클래스 메서드에서 발견되는 new 에 대한 메서드를 사용한다. 이후 잔액(balance)량을 인자로 하여 setInitialBalance: 메시지를 새 인스턴스로 전송한다. 이와 비슷하게 new는 super new에 잇따라 setInitialBalance: 를 사용하여 인스턴스를 생성하면서 재구현된다.

new
     super new setInitialBalance: 0

그림 5-4


super로 전송된 new 메시지에 대한 메서드는 실제로 어디서 발견될까? 메타클래스의 서브클래스 계층구조는 그 인스턴스의 계층구조와 동일하다. 어떤 클래스가 다른 클래스의 서브클래스인 경우, 그 클래스의 메타클래스는 그림 5.3처럼 다른 메타클래스의 서브클래스가 될 것이다. FinancialHistory 애플리케이션에서 서로 상응하는 클래스 및 메타클래스의 계층구조는 그림 5.4에 실려 있다.


아래의 표현식을 평가하면

FinancialHistory initialBalance: 350


initialBalance: 에 대한 응답은 FinancialHistory class 안에서부터, 가령 FinancialHistory에 대한 클래스 메서드에서부터 검색하기 시작한다. 선택자에 대한 메서드는 그곳에서 찾을 수 있다. 메서드는 두 개의 메서드로 구성된다.

  1. super로 new 메시지를 전송하라.
  2. 1의 결과에 setInitialBalance: 0 메시지를 전송하라.


new의 검색은 FinancialHistory 클래스의 슈퍼클래스, 즉 Object class에서 시작된다. 메서드는 그곳에서 발견되지 않으므로 검색은 슈퍼클래스 사슬을 따라 Class까지 계속된다. 메시지 선택자 new는 Class에서 발견되고, 프리미티브 메서드가 실행된다. 결과적으로 FinancialHistory의 초기화되지 않은 인스턴스가 생긴다. 이후 이 인스턴스로 setInitialBalance: 메시지가 전송된다. 응답의 검색은 인스턴스의 클래스, 즉 FinancialHistory에서 (인스턴스 메서드에서) 시작된다. 메서드는 그곳에서 발견되며, 값을 각 인스턴스 변수로 할당한다.


아래 표현식의 평가도

FinancialHistory new


비슷한 방식으로 실행된다. new에 대한 응답은 FinancialHistory class에서 (예: FinancialHistory의 클래스 메서드에서) 찾을 수 있다. 나머지 행위는 initialBalance: 에서와 동일한데, setInitialBalance: 로 전송되는 인자의 값은 예외다. 동일한 메서드의 재귀적 호출을 피하려면 인스턴스 생성 메서드는 super new를 이용해야 한다.


클래스 변수의 초기화

클래스로 전송되는 메시지는 인스턴스 생성 외에 클래스 변수의 초기화에도 많이 사용된다. 구현 설명의 변수 선언은 클래스 변수의 값은 제공하지 않고 그 이름만 제공한다. 클래스가 생성되면 명명된 클래스 변수들이 생성되지만 모두 nil 값을 갖는다. 메타클래스는 보통 클래스 변수를 초기화하는 메서드를 정의한다. 관습상 클래스 변수 초기화 메서드는 보통 클래스 초기화로 분류되는 단항 메시지 initialize 와 연관된다. 클래스 변수는 클래스와 그 메타클래스에서 모두 접근 가능하다. 클래스 변수로 값이 할당되는 작업은 인스턴스 메서드 내에서 private 메시지를 통해 간접적으로 이루어지기보다는 (인스턴스 변수에선 이러한 과정이 필수적이다) 클래스 메서드에서 이루어진다.


DeductibleHistory 예제에서 이번에는 초기화되어야 하는 클래스 변수를 포함하여 소개하고자 한다. DeductibleHistory는 FinancialHistory의 서브클래스이다. 이는 하나의 클래스 변수, MinimumDeductions를 선언한다.

클래스명 DeductibleHistory
슈퍼클래스 FinancialHistory
인스턴스 변수명 deductibleExpenditures
클래스 변수명 MinimumDeductions
클래스 메서드
instance creation
    initialBalance: amount
        | newHistory |
        newHistory   super initialBalance: amount.
        newHistory initializeDeductions.
         newHistory
    new
        | newHistory |
        newHistory   super initialBalance: 0.
        newHistory initializeDeductions.
         newHistory

class initialization
    initialize
        MinimumDeductions   2300
인스턴스 메서드
transaction recording
    spendDeductible: amount for: reason
        self spend: amount for: reason.
        deductibleExpenditures  
            deductibleExpenditures + amount
    spend: amount for: reason deducting: deductibleAmount
        self spend: amount for: reason.
        deductibleExpenditures  
            deductibleExpenditures + deductibleAmount

inquiries
    isItemizable
         deductibleExpenditures > = MinimumDeductions
    totalDeductions
         deductibleExpenditures

private
    initializeDeductions
        deductibleExpenditures   0


이번에 DeductibleHistory 버전은 5개의 인스턴스 메서드를 추가하는데, 그 중 하나는 isItemizable이다. 이 메시지에 대해서는 세금 보고서에 공제(deductions) 항목별로 작성하기에 충분히 공제액이 누적되었는지 여부에 따라 true 또는 false가 응답된다. 세법에서는 최소 2300의 공제를 받을 수 있다고 명시하므로, 누적액이 그보다 적으면 표준 공제가 사용되어야 한다. 상수 2300이 클래스 변수 MinimumDeductions에 의해 참조된다. DeductibleHistory의 인스턴스에 isItemizable 메시지를 성공적으로 전송하기 위해서는 클래스 변수 MinimumDeductions에 수치값이 할당되어야 한다. 이는 다른 인스턴스가 생성되기 전에 initialize 메시지를 클래스로 전송함으로써 이루어진다.

DeductibleHistory initialize


이 메시지는 클래스 메시지가 먼저 정의되고 나서 한 번만 전송되어야 한다. 변수는 클래스의 새로운 인스턴스에 의해 공유된다.

위의 클래스 설명에 따르면 FinancialHistory 슈퍼클래스에서처럼 initialBalance: 또는 new 메시지를 클래스로 전송하여 DeductibleHistory의 새로운 인스턴스가 생성된다. 아래와 같은 표현식을 평가한다고 가정해보자.

DeductibleHistory initialBalance: 100


표현식을 평가하기 위해 실제로 어떤 메서드가 따라와야 하는지 결정은 DeductibleHistory에 해당하는 클래스/슈퍼클래스 사슬에 따라 좌우된다. initialBalance: 에 대한 메서드는 DeductibleHistory의 클래스 메서드에서 찾을 수 있다.

initialBalance: amount
    | newHistory |
    newHistory   super initialBalance: amount
    newHistory initializeDeductions.
     newHistory


해당 메서드는 newHistory를 임시 변수로 선언한다. 메서드의 첫 번째 표현식은 임시 변수로의 할당이다.

newHistory   super initialBalance: amount


의사 변수 super는 수신자를 나타낸다. 수신자는 DeductibleHistory 클래스고, 그 클래스는 그것의 메타클래스다. 메타클래스의 슈퍼클래스는 FinancialHistory에 대한 메타클래스다. 따라서 FinancialHistory의 클래스 메서드를 살펴봄으로써 그 뒤에 따라올 메서드를 찾을 수 있다.

initialBalance: amount
     super new setInitialBalance: amount


이미 해당 메서드의 평가가 이어졌다. new에 대한 응답은 Class에서 찾을 수 있다. 원래 수신자의 새로운 인스턴스 DeductibleHistory가 생성되고 그곳으로 setInitialBalance: 가 전송된다. setInitialBalance: 의 검색은 새 인스턴스의 클래스, 즉 DeductibleHistory에서 시작한다. 하지만 결과를 찾을 수 없다. 그러면 검색은 FinancialHistory 슈퍼클래스로 진행된다. 결과가 발견되어 평가된다. FinancialHistory에서 선언된 인스턴스 변수에 값이 할당된다. 이후 DeductibleHistory에서 initialBalance:에 해당하는 클래스 메서드의 첫 번째 표현식 값은 부분적으로 초기화된 새로운 인스턴스가 된다. 이러한 새 인스턴스는 임시 변수 newHistory로 할당된다.


이후 initializeDeductions 메시지가 newHistory로 전송된다. 검색은 수신자 newHistory의 클래스인 DeductibleHistory에서 시작된다. 메서드가 발견되지 않는다. 이는 네 번째 인스턴스 변수 값을 0으로 할당한다.


인스턴스 생성 메시지의 세 번째 표현식은 새 인스턴스를 리턴한다.


DeductibleHistory 클래스를 구현하는 대안적인 방법을 다음에 소개하겠다. 이러한 대안적인 클래스 설명에서는 FinancialHistory의 인스턴스 생성 클래스 메서드가 구현되지 않는다. 대신 추가 인스턴스 변수를 설명하기 위해 private 인스턴스 메서드 메시지인 setInitialBalance: 가 오버라이드된다.

클래스명 DeductibleHistory
슈퍼클래스 FinancialHistory
인스턴스 변수명 deductibleExpenditures
클래스 변수명 MinimumDeductions
클래스 메서드
class initialization||
    initialize
        MinimumDeductions   2300
인스턴스 메서드
transaction recording
    spendDeductible: amount for: reason
        self spend: amount for: reason.
        deductibleExpenditures  
            deductibleExpenditures + amount
    spend: amount for: reason deducting: deductibleAmount
        self spend: amount for: reason.
        deductibleExpenditures  
            deductibleExpenditures + deductibleAmount

inquiries
        isItemizable
             deductibleExpenditures > = MinimumDeductions
    totalDeductions
         deductibleExpenditures

private
    setInitialBalance: amount
        super setInitialBalance: amount.
        deductibleExpenditures   0


DeductibleHistory에 대해 이러한 대안적 클래스 설명을 이용하면

DeductibleHistory initialBalance: 350


위에서 initialBalance: 에 대한 응답을 평가 시 DeductibleHistory 클래스에서 initialBalance: 를 검색하게 된다. 대상이 발견되지 않는다. 슈퍼클래스 FinancialHistory class에서 검색이 계속된다. 대상이 발견된다. 평가된 메서드는 아래 표현식으로 구성된다.

super new setInitialBalance: amount


new에 대한 메서드는 Class에서 찾을 수 있다. 새 인스턴스의 클래스 DeductibleHistory에서 시작되는 setInitialBalance: 를 검색한다. setInitialBalance: 에 대한 메서드는 DeductibleHistory에서 찾을 수 있다. DeductibleHistory에서 setInitialBalance: 의 응답으로 인해 super로 동일한 메시지를 전송하여 FinancialHistory에서 메서드의 검색이 시작된다. 결과가 발견되고, 세 개의 인스턴스 변수에 값이 할당된다. DeductibleHistory에서 setInitialBalance: 의 두 번째 표현식은 네 번째 변수를 0으로 설정한다. 원본 메시지의 결과, DeductibleHistory의 완전히 초기화된 인스턴스가 생긴다.


메서드 결정 요약(Summary of Method Determination)

메시지가 수신될 때 실제 행동을 결정할 때는 수신자의 클래스 계층구조에서 메서드를 검색하는 작업이 수반된다. 검색은 수신자의 클래스부터 시작해 슈퍼클래스 사슬로 따라간다. 마지막 슈퍼클래스 Object를 검색한 후에도 발견되지 않으면 오류가 보고된다. 수신자가 클래스일 경우 그 클래스는 메타클래스가 된다. 클래스가 응답할 수 있는 메시지는 “class methods”(클래스 메서드)라는 부분에서 구현 설명에 열거된다. 수신자가 클래스가 아닐 경우 그것이 응답할 수 있는 메시지는 "instance methods" (인스턴스 메서드)라는 부분에서 구현 설명에 열거되어 있다.


의사 변수 self는 실행되는 메서드를 호출한 메시지의 수신자를 나타낸다. self로 전송되는 메시지에 해당하는 메서드의 검색은 self의 클래스에서부터 시작된다. 의사 변수 super 또한 메시지의 수신자를 나타낸다. super로 전송되는 메시지에 해당하는 메서드의 검색은 실행되는 메서드가 발견된 클래스의 슈퍼클래스에서 시작된다.


이로써 Smalltalk-80 프로그래밍 언어의 설명은 끝이 난다. 시스템을 사용하기 위해서는 프로그래머가 시스템 클래스에 관한 일반적 지식을 겸비해야 한다. 제 2부에서는 시스템 클래스 각각에 대한 프로토콜의 설명을 상세하게 제공하고, 때로는 시스템의 구현 설명을 제시함으로써 예제를 제공할 것이다. 제 3부에서는 중간 크기의 애플리케이션을 소개한다. 실제 시스템 클래스의 세부내용을 연구하기 전에 크기가 큰 애플리케이션을 정의하는 것이 궁금하다면 제 3부로 건너뛰어도 좋다.


용어 정리

메타클래스(metaclass) 클래스의 클래스.
클래스 메타클래스를 제외한 모든 클래스의 추상 슈퍼클래스.
Metaclass 인스턴스가 클래스의 클래스에 해당하는 클래스.


Notes