SqueakByExample:5.7

From 흡혈양파의 번역工房
Revision as of 05:47, 30 August 2012 by Onionmixer (talk | contribs)
Jump to navigation Jump to search

공유 변수

이제 우리는, 우리의 다섯가지 규칙들: 공유된 변수들, 에 의해 쉽게 다루어 지지 않는 스몰토크의 일면을 살펴볼 것입니다.

스몰토크는 3가지 종류의 공유된 변수들이 있습니다: (1) 글로벌 공유 변수 (2) 인스턴스와 클래스 사이에 공유된 변수(클래스 변수) 그리고 (3)클래스의 그룹 사이에서 공유된 변수[그룹(pool) 변수들)모든 이 공유된 변수들은 우리에게, 그 변수들이 정말로 공유되었다는 것을 경고하기 위해 대문자로 시작됩니다.


글로벌 변수(Global variables)

스퀵에서, 모든 글로벌 변수는 클래스 SystemDictionary의 인스턴스로서 실행된 스몰토크라 불리는 namespace에 저장됩니다. 글로벌 변수는 어디서나 접근할 수 있습니다. 모든 클래스는 글로벌 변수에 의해 이름이 작성되며; 이에 더하며, 몇 가지 글로벌 변수는 특별한 이름을 만드는 작업에 사용하거나 일반적으로 유용한 오브젝트에 사용됩니다.

변수 Transcript는 스크롤되는 창(a scrolling window)에 기록하는 스트림(stream)인 Transcript Stream의 인스턴스 이름을 작성하고, Transcript에서 다음 라인으로 이동합니다.

Transcript show: 'Squeak is fun and powerful' ; cr

do it 을 클릭하기 전에, Tools flap에서 Transcript를 드레그하여 트랜스크립트Transcript를 엽니다.


HINT 트랜스크립트Transcript에 기록하는 작업은 특별히 트랜스크립트Transcript창이 열렸을 때 느리게 진행됩니다. 그러므로, 만약 여러분이, 트랜스크립트Transcript에 기록을 할 때, 매우 느려지는 것을 경험하였다면, 그 창을 닫는 것을 고려해 보십시오.


다른 유용한 글로벌 변수들

  • 스몰토크는 스몰토크 자체를 포함하여 모든 글로벌 변수를 정의하는 SystemDictionary의 인스턴스 입니다. 이 사전에 대한 키들은 스몰토크 코드에서 글로벌 오브젝트 이름(global object name)을 만드는 심볼들입니다. 그러므로 예를 들어,
    Smalltalk at: #Boolean      Boolean
    

    스몰토크 자체가 글로벌 변수이므로,
    Smalltalk at: #Smalltalk      a SystemDictionary(lots of globals)}
    

    그리고
    (Smalltalk at: #Smalltalk) == Smalltalk       true
    
  • Sensor는 EventSensor의 인스턴스이며, Squeak에 입력을 표시합니다. 예를 들면, Sensor eyborad는 키보드에 다음 문자 입력을 답하며, Sensor mousePoint가 Point는 현재 마우스 위치를 가리키고 있다고 답하는 반면에, 만약 왼쪽 쉬프트 키가 눌려 있는 상태인 경우 Sensor leftShiftDown은 true를 답합니다. • World는 화면을 표시하는 PasteUpMorph의 인스턴스입니다. World bounds 는 전체 화면 공간을 정의하는 직사각형을 답으로 내놓으며, 화면의 모든 모프(Morph)는 World의 서브모프(Submorphs)입니다.
  • ActiveHand는 HandMorph의 현재 인스턴스이며, 커서의 그래픽 표현입니다. ActiveHand의 서브모프(submorphs )는 마우스로 드레그된 모든 것을 붙잡습니다.
  • Undeclared (공표되지 않은 변수)는 다른 사전입니다- 이것은 모든 공표되지 않은 변수들(undeclared variables)을 포함합니다. 만약 여러분이 공표되지 않은 함수를 참조하는 메서드를 작성하실 것이라면, 브라우저는 보통 그것을 공표하기 위해 여러분을 프롬프트 상태로 만들 것입니다. 그럼에도 불구하고, 만약 여러분이 나중에 그 공표를 지운다면, 코드는 공표되지 않은 변수들을 참조할 것입니다. Undeclared (공표되지 않은 함수들)을 정밀 검사하는 작업은 때때로 이상한 동작 설명을 도울 수 있습니다.
  • SystemOrganization 은 SystemOrganizer의 인스턴스입니다: 이것은 패키지에 클래스들의 조직(organization)을 기록합니다. 좀더 정확하게 말하자면, 이것은 클래스들의 이름을 그룹으로 만들어 분류(categorizes)합니다. 그러므로
    SystemOrganization categoryOfElement: #Magnitude      #'Kernel--Numbers'
    


현재의 실행은 글로벌 변수들의 사용을 엄격히 제한하므로, 인스턴스 변수 또는 클래스 변수를 사용하거나, 글로벌 변수들에 접근하기 위해 클래스 메서드를 제공하는 방법이 더 나은 방법입니다. 실제로, 만약 스퀵이 현재 버전의 스크래치(프로그래밍 언어의 일종:역주)로부터 실행될 것이었다면, 클래스가 아닌 대부분의 글로벌 함수들은 아마도 싱글톤(singletons)으로 대체될 것입니다.

글로벌 변수를 정의하는 일상적인 방법은, 대문자로 변경되었지만 공표되지 않은 식별자(identifier)에 대한 할당(assignment)에, 단지 do it을 실행하는 것입니다. Parser는 그 다음, 여러분을 위해 공표할 글로벌 변수를 제공할 것입니다. 만약 여러분이 프로그램적으로 글로벌 변수들을 정의하기 원하신다면, Smalltalk at: #AGlobalName put: nil을 실행할 수 있습니다. 이것을 제거하려면, 스몰토크 removeKey: #AGlobalName를 실행합니다.


클래스 변수

때때로, 우리는 모든 클래스의 인스턴스들과 클래스 자체물들 사이에 몇몇 데이터를 공유할 필요가 있습니다. 이 작업은 클래스 변수를 사용하여 수행할 수 있습니다. 클래스 변수라는 용어는 변수의 수명이 클래스의 수명과 같다는 의미를 갖습니다. 그럼에도 불구하고, 이 용어가 담지 못하는 내용은, 이 변수들이 그림 5.5에 보이는 것처럼, 클래스 자체 뿐만 아니라 클래스의 모든 인스턴스들 사이에서도 공유된다는 것을 포괄합니다. 실제로, 클래스 변수 보다 좀 더 나은 이름은 ‘공유된 변수’ 일 것입니다. 왜냐하면, 이 이름이 좀더 명확하게 그 변수의 역할을 설명해주기 때문이며 또한, 변수들이 수정되었을 경우, 사용의 위험성을 사용자에게 경고하기 때문입니다.


그림 5.5: 다양한 변수들에 접근하는 인스턴스와 클래스 메서드


그림 5.5에서, 우리는 rgb와 cachedDepth가 Color의 인스턴스 변수인 것을 알 수 있으며, Color 인스턴스에 유일하게 접근할 수 있는 대상들임을 또한 알 수 있습니다. 우리는 또한 superclass,subclass,methodDic와 다른 것들이 클래스 인스턴스 변수임을 알 수 있습니다. 예컨데, 인스턴스 변수들은 오직 color 클래스에 접근할 수 있습니다.

그러나 우리는 또한 약간 새로운 것을 볼 수 있습니다: ColorNames 와 CachedColormaps는 Color를 위해 정의된 class 변수입니다. 이 변수들의 대문자화는 우리에게 이 변수들이 공유되었다는 힌트를 제공합니다. 사실, Color의 모든 인스턴스들은 이 공유된 변수들에 접근할 수 있을 뿐만 아니라, Color 클래스 자체와 그 클래스의 모든 subclasses에게도 접근할 수 있습니다. 인스턴스 메서드와 클래스 메서드 둘 모두, 이 공유된 변수들에 접근할 수 있습니다.

클래스 변수는 클래스 정의 탬플릿(the class definition template)에 공표됩니다. 예를 들면, 클래스 색상은 color 생성 속도를 높이기 위해 많은 수의 클래스 변수들을 정의하며, 그 변수의 정의는 아래에 보입니다. (클래스 5.20)


클래스 5.20: Color와 그것의 클래스 변수(class variables)

Object subclass: #Color
  instanceVariableNames: 'rgb cachedDepth cachedBitPattern'
  classVariableNames: 'Black Blue BlueShift Brown CachedColormaps ColorChart
  ColorNames ComponentMask ComponentMax Cyan DarkGray Gray
  GrayToIndexMap Green GreenShift HalfComponentMask HighLightBitmaps
  IndexedColors LightBlue LightBrown LightCyan LightGray LightGreen
  LightMagenta LightOrange LightRed LightYellow Magenta MaskingMap Orange
  PaleBlue PaleBuff PaleGreen PaleMagenta PaleOrange PalePeach PaleRed
  PaleTan PaleYellow PureBlue PureCyan PureGreen PureMagenta PureRed
  PureYellow RandomStream Red RedShift TranslucentPatterns Transparent
  VeryDarkGray VeryLightGray VeryPaleRed VeryVeryDarkGray
  VeryVeryLightGray White Yellow'
  poolDictionaries: ''
  category: 'Graphics--Primitives'


클래스 변수 ColorNames는 빈번하게 사용되는 색상의 이름을 포함하고 있는 배열(array)입니다. 이 배열(array)는 color의 모든 인스턴스에 의해 공유되며, 그 배열의 서브클래스는 TranslucentColor입니다. 이 배열은 모든 인스턴스와 클래스 메서드들로 부터 접근할 수 있습니다.

ColorNames는 일단 Color class»initializeNames에서 초기화되지만, Color의 인스턴스로부터 접근됩니다. 메서드 Color»name은 color의 이름을 찾기 위해 변수를 사용합니다. 대부분의 color가 이름을 갖고 있지 않기 대문에, 모든 color에 인스턴스 변수 이름을 더하는 것이 적합한 것으로 간주됩니다.


클래스 초기화(Class initialization)

클래스 변수의 존재는, 다음과 같은 질문을 떠오르게 합니다: 어떻게 이 변수를 초기화 할까? 이것에 대한 한 가지 해결책은 게으른 초기화(lazy initialization) 입니다. 이 초기화는 실행될 때, 변수가 아직 초기화 되지 않았을 경우, 변수를 초기화 하는 accessor(접근자) 메서드를 소개함으로써, 수행됩니다. 이 게으른 초기화는 우리가 항상 accessor를 사용하고 클래스 변수를 결코 직접 사용하면 안 된다는 사실을 암시합니다. 이 작업은 더 나아가 accessor send(접근자 보내기)와 초기화 테스트의 부담을 사용자에게 부과합니다. 또한 이 초기화는 실제로 더 이상 공유되지 않기 때문에, 클래스 변수 사용을 거의 틀림없이 무산시킵니다.


메서드 5.21: Color class»colorNames

Color class»colorNames
  ColorNames ifNil: [self initializeNames].
   ColorNames


다른 해결책은, 클래스 메서드 초기화(the class method initialize)를 재지정하는 것입니다.

메서드 5.22: Color class»initialize

Color class»initialize
  ...
  self initializeNames


만약 여러분이 이 해결책을 채택한다면, 여러분이 초기화 메서드를 정의한 다음(예를 들면 Color initialize를 평가하여 초기화 메서드를 불러올 필요성을 기억하실 필요가 있습니다. 비록 class side initialize methods(클래스 사이드 초기화 메서드)들이 코드가 메모리에 로드 될 때, 자동으로 실행되지만, 그 메서드 들은 브라우저에 처음 타이핑 되거나 컴파일 되거나 또는 수정되거나 다시 컴파일 될 때, 자동으로 실행되지 않습니다.


공동변수(Pool variables)

공동 변수들(pool variables)은 상속으로 연관되지 않을 수 있는 여러 개의 클래스들 사이에서 공유되는 변수들입니다. 공동 변수들은 본래 pool dictionary에 저장되지만, 지금은, 개별 클래스(Sharedpool의 서브클래스)의 클래스 변수로서 정의되어야만 합니다. 우리가 드릴 조언은 이 변수들을 여러분들이 회피하시라는 것이며, 그 이유는 여러분들이 매우 드물고 특정한 상황들에서만 이 변수들이 필요할 것이기 때문입니다. 이 지면에서 우리의 목표는 여러분이 코드를 읽을 때, 이해하실 수 있도록 공동 변수(pool variables)를 충분히 설명하는 것입니다.

공동 변수(pool variable)에 접근하는 클래스는 그 클래스 정의에서 반드시 공용(the pool)을 언급해야 합니다. 예를 들면, 클래스 Text는 그것이 pool dictionary Textcontansts를 사용하고 있다는 것을 가리키며, 이것은 CR과 LF와 같은 모든 문자 상수(the text constant)를 포함합니다. 이 사전은 예를 들면 캐리지 리턴(the carriage return)문자와 같은 값 Character cr에 묶인 key #CR을 갖고 있습니다.


클래스 5.23: Text 클래스에 있는 Pool dictionaries

ArrayedCollection subclass: #Text
  instanceVariableNames: 'string runs'
  classVariableNames: ''
  poolDictionaries: TextConstants
  category: 'Collections--Text'


이는 예를 들어, 명백한 딕셔너리 검색 보다는 변수 구문(variable syntax)를 사용하여, 메서드 바디에 있는 딕셔너리의 key들에 접근하기 위해 클래스 Text의 메서드를 허용합니다. 예시로, 우리는 다음 메서드를 작성할 수 있을 것입니다.


메서드 5.24: Text»testCR

Text»testCR
   CR == Character cr


다시 한번, 우리는 여러분에게 pool 변수와(pool variables) pool 딕셔너리(pool dictionarieis) 사용을 피하실 것을 권장합니다.

Notes