SqueakByExample:2.7: Difference between revisions

From 흡혈양파의 번역工房
Jump to navigation Jump to search
(주석부분 추가)
(검수 20180719)
 
(40 intermediate revisions by the same user not shown)
Line 1: Line 1:
==프로토콜에 메소드를 구성하기==
==프로토콜에 메서드 연계하기==


우리가 좀더 많은 다른 메소드를 정의하기 전에, 브라우저의 상단에 있는 세번째 패널을 잠시 찾아보겠습니다. 브라우저의 첫 번째 패널은, 클래스들을 카테고리화하여, 두 번째 패널에 있는 매우 긴 클래스 이름의 목록에 압도되지 않게 해주며, 동일한 방식으로 세 번째 패널은 네 번째 패널에 있는 매우 긴 클래스 이름의 목록에 압도되지 않게 해줍니다. 이러한 메소드의 카테고리들을 “프로토콜”로 부릅니다.
좀 더 다양한 메서드를 정의하기 전에, 브라우저의 상단에 있는 세번째 pane 을 잠시 보겠습니다. 브라우저의 첫 번째 pane 은, 클래스를 카테고리화해서, 두 번째 pane 에 있는 매우 긴 클래스 목록에 사용자가 놀라지 않게 해주며, 동일한 방식으로 세 번째 pane 은 네 번째 pane 에 있는 매우 긴 메서드 목록에 당황하지 않게 해줍니다. 이러한 메서드의 카테고리를 "프로토콜<sup>Protocol</sup>" 이라고 부릅니다.


만약 클래스에 단지 몇 개의 메소드만 있다면, 프로토콜에 의해 제공되는 계층도의 추가 레벨은 정말로 필요한 것이 아닙니다. 이것이 브라우저가 우리가 배울 때 놀라지 않을 --all--  가상 프로토콜을 제공하는 이유이며, 이 가상 프로토콜은 클래스의 모든 메소드를 포함하고 있습니다.
클래스에 메서드가 몇개 없는 경우라면, 프로토콜이 제공하는 계층형 추가 레벨은 딱히 필요가 없습니다. 브라우저에서는 클래스의 모든 메서드를 포함하는 --all--  이라고 되어있는 가상 프로토콜을 제공하는것에 놀랄 필요도 없습니다.


[[image:Categorize.png|none|267px|thumb|그림 2.10: 모든 카테고리화되지 않은 메소드를 카테고리화 하기]]
[[image:Categorize.png|none|267px|thumb|그림 2.10: 분류하지 않은 메서드의 분류]]


만약 여러분이 이 예를 따라 하였다면, 세 번째 패널은 아직 분류되지 않은 프로토콜을 포함할 가능성이 높습니다.


{{CommentSqueak|노랑-버튼 메뉴 아이템을 선택하고 아이템을 수정하기 위해 {{Template:HighlightGray|categorize all uncategorized}}를 클릭한 후, '''initialization(초기화)'''로 불리는 새로운 프로토콜에 초기화 메소드(the initialize methods)를 이동시킵니다.}}
예제를 따라 하셨다면, 세 번째 pane 은 ''아직 분류되지 않은 프로토콜'' 을 포함하고 있을 가능성이 높습니다.


이것이 올바른 프로토콜 인지 어떻게 스퀵이 알 수 있을까요? 일반적으로 스퀵은 알수가 없지만, 이번 경우에는 수퍼클래스에 (initialize)초기화 메소드가 있으므로, 스퀵은 우리의 (initialize)초기화 메소드가 재지정하는 카테고리 동일한 카테고리로 이동하게 됩니다.


여러분은 스퀵이 이미 initialize(초기화) 메소드를, initialization(초기화) 프로토콜 안에 집어 넣었다는 것을 발견할 것입니다. 만약 그렇게 되었다면, 여러분이 AutomaticMethodCategorizer라 불리는 패키지를 여러분의 이미지에 로드 하였기 때문입니다.
{{CommentSqueak|노랑-버튼 메뉴 항목을 선택하고 이 항목을 수정하기 위해 {{Template:HighlightGray|categorize all uncategorized}}를 선택한 후, {{HighlightBold|initialization}}이라고 하는 새로운 프로토콜로 {{HighlightBold|initialize}} 메서드를 이동하십시오.}}


'''인쇄상의 관례.''' 스몰토크사용자(smalltalkers)는 빈번하게 표기법 “>>”을 메소드가 속한 클래스를 알아내기 위해 사용합니다. 예를 들어, 클래스 '''SBEGame'''에 있는 '''cellsPerSide''' 메소드는 '''SBEGame>>cellsPerSide'''로 부를 것입니다. 이것이 스몰토크 구문(smalltalk syntax)을 아님을 나타내기 위해, 우리는 대신 특별한 심볼 >>을 사용할 것이므로, 이 메소드는 '''SBEGame>>cellsPerSide'''로서 텍스트에 나타날 것입니다.


지금부터 우리는 이 책에서 메소드를 여러분에게 보여드릴 때, 이 폼으로 메소드의 이름을 작성할 것입니다 물론, 브라우저에 코드를 실제로 타이핑 할 때, 클래스 이름 또는 >>;를 타이핑할 필요가 없으며, 단지 클래스 패널에 적합한 클래스가 선택되었는지를 확인하십시오.  
어떻게 스퀵은 이게 올바른 프로토콜인지를 알았을까요? 글쎄요, 일반적인 경우라면 스퀵은 알아채지 못하지만, 이 경우에서는 상위 클래스에 initialize 메서드가 있기 때문에, 스퀵에서는 재정의한 initialize 메서드를 같은 카테고리에 있어야 한다고 가정했습니다.


자 이제, '''SBEGame>>initialize''' 메소드에 의해 사용되는 다른 두 개의 메소드를 정의하겠습니다. 둘 모두는 '''initialization(초기화)''' 프로토콜 안으로 이동할 수 있습니다.


스퀵이 이미 initialize 메서드를 initialization 프로토콜에 넣었음을 발견했습니다. 정말 그렇다면, 아마 AutomaticMethodCategorizer 라는 패키지를 사용자의 이미지<ref name="역자주1">squeak vm 상에서 작동되는 squeak image 를 의미합니다</ref>에 불러왔기 때문일지도 모릅니다.


메소드 2.5  상수(constant) 메소드
 
'''표기 관례.''' Smalltalk 사용자는 메서드가 속하는 클래스를 구분하기 위해 ">>" 표기를 자주 사용하기 때문에, '''SBEGame''' 에 있는 '''cellsPerSide''' 메서드는 '''SBEGame>>cellsPerSide''' 라고 표기합니다. 이러한 표기방법이 Smalltalk 언어의 문법이 아님을 나타내기 위해, >> 대신에 >> 라는 특별한 심볼을 사용해서, 본문상에서는 '''SBEGame>>cellsPerSide''' 처럼 보이도록 표기하겠습니다.
 
 
지금부터 이 책에서 메서드를 보여드릴 때는, 이런 표기양식으로 메서드의 이름을 작성할 것입니다 물론, 브라우저에 코드를 실제로 타이핑 할 때, 클래스 이름 또는 >> 기호를 입력할 필요는 없으며, 단지 클래스 pane 에서 적당한 클래스를 선택했는지만 확인하면 됩니다.
 
 
자 이제, '''SBEGame>>initialize''' 메서드에서 사용하는 다른 두 개의 메서드를 정의하도록 하겠습니다. 두 메서드 모두 '''initialization''' 프로토콜로 이동할 수 있습니다.
 
 
메서드 2.5  상수 메서드
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
SBEGame»cellsPerSide
SBEGame>>cellsPerSide
   "The number of cells along each side of the game"
   "The number of cells along each side of the game"
   ↑ 10
   ↑ 10
</syntaxhighlight>
</syntaxhighlight>


메소드는 더 단순해 질 수 없습니다: 메소드는 상수 10을 답으로 제시합니다. 메소드로서 상수(constants)를 나타내는 장점은 만약 프로그램이 진화하여, 상수가 몇 가지 다른 특성들에 의존되어 있다면 메소드는 이 10을 계산하기 위해 변경될 있는 것입니다.
 
메서드는 이상 단순해 질 수 없습니다. 메서드는 상수 10을 반환합니다. 메서드로서 상수를 나타내는 장점은, 프로그램이 커지면서 상수가 몇 가지 다른 특성에 의존하게 되는 경우, 메서드 내부의 값의 변경을 통한 계산등을 위해 현재 10 을 쉽게 변경할 있습니다.




메소드 2.6 initialization helper(초기화 헬퍼) 메소드
메서드 2.6 헬퍼 메서드 초기화
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
SBEGame»newCellAt: i at: j
SBEGame>>newCellAt: i at: j
   "Create a cell for position (i,j) and add it to my on—screen
   "Create a cell for position (i,j) and add it to my on-screen
   representation at the appropriate screen position. Answer the new cell"
   representation at the appropriate screen position. Answer the new cell"
   | c origin |
   | c origin |
Line 41: Line 49:
   origin := self innerBounds origin.
   origin := self innerBounds origin.
   self addMorph: c.
   self addMorph: c.
   c position: ((i -- 1) * c width) @ ((j -- 1) * c height) + origin.
   c position: ((i - 1) * c width) @ ((j - 1) * c height) + origin.
   c mouseAction: [self toggleNeighboursOfCellAt: i at: j].
   c mouseAction: [self toggleNeighboursOfCellAt: i at: j].
  Add the methods SBEGame»cellsPerSide and SBEGame»newCellAt:at:.
  Confirm the spelling of the new selectors toggleNeighboursOfCellAt:at: and
  mouseAction:.
</syntaxhighlight>
</syntaxhighlight>




{{CommentSqueak|메소드 SBEGame»cellsPerSide and SBEGame»newCellAt:at:를 추가합니다.}}
{{CommentSqueak|{{HighlightBold|SBEGame>>cellsPerSide}} 메서드와 {{HighlightBold|SBEGame>>newCellAt:at:}} 메서드를 추가하십시오.}}
 


새로운 선택자<sup>selector</sup> '''toggleNeighboursOfCellAt:at:'''과 '''mouseAction:'''의 철자를 확인하십시오.


새로운 선택자(selectors) '''toggleNeighboursOfCellAt:at:''' 와 '''mouseAction:''' 의 스펠링을 확인합니다.


메소드 2.6은 셀의 메트릭스에 위치(i,j)에 특별히 지정된 새로운 SBECell로 응답합니다. 마지막 라인은 블록 '''[self toggleNeighboursOfCellAt: i at: j ]''' 되도록 새로운 셀의 mouseAction을 정의합니다. 실제로, 이 정의는 마우스가 클릭될 때 실행할 콜백 동작을 정의합니다. 이에 대응하는 메소드(the corresponding method)또한 정의될 필요가 있습니다.
메서드 2.6 은 Matrix 에서 게임상의 cell 에 대한 특정 위치(i,j)에 특별히 지정된 새로운 SBECell 로 응답합니다. 마지막 행은  '''[self toggleNeighboursOfCellAt: i at: j ]''' 블록이 되도록 새로운 cell 의 mouseAction 을 정의합니다. 실제로, 이 정의는 마우스를 클릭할 때 실행할 callback 동작을 정의합니다. 이 내용에 대응하는 메서드 또한 정의해야 합니다.




메소드 2.7: 콜백메소드(The callback method)
메서드 2.7: callback 메서드
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
SBEGame»toggleNeighboursOfCellAt: i at: j
SBEGame>>toggleNeighboursOfCellAt: i at: j
   (i > 1) ifTrue: [ (cells at: i -- 1 at: j ) toggleState].
   (i > 1) ifTrue: [ (cells at: i - 1 at: j ) toggleState].
   (i < self cellsPerSide) ifTrue: [ (cells at: i + 1 at: j) toggleState].
   (i < self cellsPerSide) ifTrue: [ (cells at: i + 1 at: j) toggleState].
   (j > 1) ifTrue: [ (cells at: i at: j -- 1) toggleState].
   (j > 1) ifTrue: [ (cells at: i at: j - 1) toggleState].
   (j < self cellsPerSide) ifTrue: [ (cells at: i at: j + 1) toggleState].
   (j < self cellsPerSide) ifTrue: [ (cells at: i at: j + 1) toggleState].
</syntaxhighlight>
</syntaxhighlight>


메소드 2.7은 (i,j)의 동서남북에 4 개 셀의 상태를 토글합니다. 유일한 문제는 보드가 유한하므로, 우리가 셀의 상태를 토글 하기 전에, 이웃한 셀이 존재하도록 철저히 해두어야 한다는 것입니다.
 
메서드 2.7은 게임상 (i,j) cell 네 방향에 있는 4개의 칸 상태를 토글합니다. 유일한 문제가 있다면 보드의 크기는 유한하기 때문에, 사용자가 cell 의 상태를 토글 하기 전에, 이웃한 cell 이 존재할지에 대해 철저히 대비를 해두어야 한다는 것입니다.




{{CommentSqueak|'''game logic'''이라 불리는 새로운 프로토콜에 이 메소드를 배치합니다.}}
{{CommentSqueak|{{HighlightBold|game logic}}이라 불리는 프로토콜에 callback 메서드를 배치하십시오.}}




메소드를 이동하려면, 단순히 그 메소드의 이름을 클릭하고 새롭게 만든 프로토콜(그림 2.11)로 드레그합니다.
메서드를 이동하려면, 간단하게 이름을 클릭하고, 새로 만든 프로토콜(그림 2.11)로 끌어다 놓습니다.


[[image:DragMethod.png|none|588px|thumb|그림 2.11 메소드를 프로토콜에 드레그하기]]


Quinto game을 완료하려면, 마우스 이벤트(mouse events)를 핸들 하기 위해 클래스 SBEcell에서 두 개 이상의 메소드를 정의할 필요가 있습니다.
[[image:DragMethod.png|none|588px|thumb|그림 2.11 메서드를 프로토콜에 드래그하기]]




메소드 2.8: 전형적인 setter(설정자) 메소드
Quinto 게임을 완성하려면, 마우스 이벤트를 다루기 위해 SBEcell 클래스에서 두 개 이상의 메서드를 정의할 필요가 있습니다.
 
 
메서드 2.8: 전형적인 setter 메서드
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
SBECell»mouseAction: aBlock
SBECell>>mouseAction: aBlock
   ↑ mouseAction := aBlock
   ↑ mouseAction := aBlock
</syntaxhighlight>
</syntaxhighlight>


메소드 2.8은 인수에 셀의 mouseAction(마우스액션) 변수를 설정하고 새로운 값을 답하는 것 이외에 다른 어떤 역할도 하지 않습니다. 이러한 방식으로 인스턴스 변수의 값을 변경하는 모든 메소드는 setter(세터) 메소드라 부르며, 인스턴스 변수의 현재 값을 답하는 메소드는 getter(게터)메소드라 부릅니다.


만약 여러분이 다른 프로그래밍 언어로 getter(게터)와 세터(setters) 메소드를 사용하셨다면, setmouseAction과 getmouseAction으로 이 메소드들을 지칭하였을 것입니다. 스몰토크 관례는 다릅니다. getter(게터)는 변수가 갖는 이름과 같은 동일한 이름으로 지어져야 하며, setter(세터)는 유사한 이름으로 만들어지지만, 마지막에 “:”를 갖고 있으므로, mouseAction과 ‘mouseAction:’ 메소드는 getter(게터) 메소드라 불리는 인스턴스 변수의 현재 값으로 대답합니다.
메서드 2.8 은 cell 의 mouseAction 변수를 인수로 설정 한 이후에 새 값에 응답합니다. 이처럼 인스턴스 변수의 값을 ''바꾸는'' 메서드를 ''setter 메서드''라고 하며, 인스턴스 변수의 현재 값을 ''응답하는'' 메서드를 ''getter 메서드'' 라고 부릅니다.


총괄하면, setters(세터) 와 getter(게터)는 accessor(접근자)메소드로 불리며, 관례적으로,  accessing(접근) 프로토콜 안에 배치되어야 합니다. 스몰토크에서, 모든 인스턴스 변수는 그 변수들을 소유하는 오브젝트 전용이며, 스몰토크 언어에서 이러한 변수들을 읽거나 작성하기 위한 다른 오브젝트는 이 인수턴스 변수와 같은1 accessor (접근자 메소드)가 유일한 방법입니다.<ref name="주석2-1">사실 인스턴스 변수는 서브클래스 안에서도 접근할 수 있습니다.</ref>


독자가 다른 프로그래밍 언어에서 getters 와 setters 를 사용해봤다면, setmouseAction 과 getmouseAction 이라고 하는 메서드를 기대했겠지만, 스몰토크의 표기 관례는 다릅니다. getter 메서드는 변수의 이름과 같은 이름이어야 하며, setter 메서드는 비슷한 이름으로 만들어지지만, 마지막에 ":" 을 붙입니다. 따라서 mouseAction 과 'mouseAction:' 이 됩니다.


{{CommentSqueak|클래스 '''SBECell'''로 가서, '''Cell>>mouseAction'''을 정의하고 그것을 '''accessing(접근)'''프로토콜에 넣습니다.}}


정리하자면, setter 와 getter 는 접근자 메서드라고 불리며, 관례상, accessing 프로토콜로 분류됩니다. Smalltalk 에서, ''모든'' 인스턴스 변수는 객체에서 private으로 취급되며, Smalltak 언어에서 다른 객체를 통해 이러한 인스턴스 변수를 읽고 쓰려면, 앞에서 설명한것처럼 접근자 메서드<ref name="주석2-1">사실 하위클래스에서는 접근이 가능합니다</ref>를 통해야 합니다.<ref name="역자주1">이것은 객체의 속성중 캡슐화에 관련된 부분입니다. http://ta.onionmixer.net/wordpress/?p=126 이 내용을 참고해주세요</ref>


마지막으로 우리는 메소드 mouseUp:을 정의할 필요가 있으며, 이 메소드는 화면에서 셀 위에 마우스가 머무는 동안 마우스 버튼이 릴리스되면,  GUI 프레임워크에 의해 자동으로 불러오기가 될 것입니다.


{{CommentSqueak|{{HighlightBold|SBECell}} 클래스로 가서, {{HighlightBold|SBECell>>mouseAction:}} 을 정의하고 {{HighlightBold|accessing}} 프로토콜에 넣으십시오.}}


메소드 2.9 이벤트 헨들러 (An event handler)
 
마지막으로 메서드 mouseUp:을 정의해야 하며, 이 메서드는 화면의 칸 위에 마우스가 머무는 동안 마우스 버튼을 떼면,  GUI 프레임워크에서 자동으로 호출될 것입니다.
 
 
메서드 2.9 이벤트 핸들러
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
SBECell»mouseUp: anEvent
SBECell>>mouseUp: anEvent
mouseAction value
mouseAction value
</syntaxhighlight>
</syntaxhighlight>




{{CommentSqueak|메소드 '''SBECell>>mouseUp:''' 추가하고, {{Template:HighlightGray|모든 카테고리화 되지 않은}} 메소드들의 카테고리를 만듭니다.}}
{{CommentSqueak|'''SBECell>>mouseUp:''' 메서드를 추가하고, 메서드를 {{Template:HighlightGray|categorize all uncategorized}} 하십시오.}}




메소드가 하는 작업은 인스턴스 변수 '''mouseAction'''에 저장되어 있는 오브젝트에 메시지 값을 보내는 것입니다. 우리가, 뒤이은 코드 조각을 '''mouseAction'''에 할당했던,  '''SBEGame»newCellAt: i at:'''에서 그 메소드를 다시 불러냅니다:  
메서드는 인스턴스 변수 '''mouseAction'''에 저장한 객체로 value 메시지를 보내서 처리하도록 동작합니다. 사용자가 '''SBEGame>>newCellAt: i at:''' 에서 '''mouseAction''' 에 인자로 대입한 다음의 코드가 다시 호출됩니다:


<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
Line 114: Line 127:
</syntaxhighlight>
</syntaxhighlight>


'''Value''' 메시지를 보내는 작업은 이 코드 조각이 평가되고, 결론적으로 셀의 상태의 토글 되도록 만듭니다.
'''value''' 메시지를 보내면, 해당되는 코드부분이 실행되며 cell 의 상태를 전환합니다.
 
 


==Notes==
==Notes==

Latest revision as of 08:52, 19 July 2018

프로토콜에 메서드 연계하기

좀 더 다양한 메서드를 정의하기 전에, 브라우저의 상단에 있는 세번째 pane 을 잠시 보겠습니다. 브라우저의 첫 번째 pane 은, 클래스를 카테고리화해서, 두 번째 pane 에 있는 매우 긴 클래스 목록에 사용자가 놀라지 않게 해주며, 동일한 방식으로 세 번째 pane 은 네 번째 pane 에 있는 매우 긴 메서드 목록에 당황하지 않게 해줍니다. 이러한 메서드의 카테고리를 "프로토콜Protocol" 이라고 부릅니다.

클래스에 메서드가 몇개 없는 경우라면, 프로토콜이 제공하는 계층형 추가 레벨은 딱히 필요가 없습니다. 브라우저에서는 클래스의 모든 메서드를 포함하는 --all-- 이라고 되어있는 가상 프로토콜을 제공하는것에 놀랄 필요도 없습니다.

그림 2.10: 분류하지 않은 메서드의 분류


이 예제를 따라 하셨다면, 세 번째 pane 은 아직 분류되지 않은 프로토콜 을 포함하고 있을 가능성이 높습니다.


Squeak comment.png노랑-버튼 메뉴 항목을 선택하고 이 항목을 수정하기 위해 categorize all uncategorized를 선택한 후, initialization이라고 하는 새로운 프로토콜로 initialize 메서드를 이동하십시오.


어떻게 스퀵은 이게 올바른 프로토콜인지를 알았을까요? 글쎄요, 일반적인 경우라면 스퀵은 알아채지 못하지만, 이 경우에서는 상위 클래스에 initialize 메서드가 있기 때문에, 스퀵에서는 재정의한 initialize 메서드를 같은 카테고리에 있어야 한다고 가정했습니다.


스퀵이 이미 initialize 메서드를 initialization 프로토콜에 넣었음을 발견했습니다. 정말 그렇다면, 아마 AutomaticMethodCategorizer 라는 패키지를 사용자의 이미지[1]에 불러왔기 때문일지도 모릅니다.


표기 관례. Smalltalk 사용자는 메서드가 속하는 클래스를 구분하기 위해 ">>" 표기를 자주 사용하기 때문에, SBEGame 에 있는 cellsPerSide 메서드는 SBEGame>>cellsPerSide 라고 표기합니다. 이러한 표기방법이 Smalltalk 언어의 문법이 아님을 나타내기 위해, >> 대신에 >> 라는 특별한 심볼을 사용해서, 본문상에서는 SBEGame>>cellsPerSide 처럼 보이도록 표기하겠습니다.


지금부터 이 책에서 메서드를 보여드릴 때는, 이런 표기양식으로 메서드의 이름을 작성할 것입니다 물론, 브라우저에 코드를 실제로 타이핑 할 때, 클래스 이름 또는 >> 기호를 입력할 필요는 없으며, 단지 클래스 pane 에서 적당한 클래스를 선택했는지만 확인하면 됩니다.


자 이제, SBEGame>>initialize 메서드에서 사용하는 다른 두 개의 메서드를 정의하도록 하겠습니다. 두 메서드 모두 initialization 프로토콜로 이동할 수 있습니다.


메서드 2.5 상수 메서드

SBEGame>>cellsPerSide
  "The number of cells along each side of the game"
   10


이 메서드는 더 이상 단순해 질 수 없습니다. 이 메서드는 상수 10을 반환합니다. 메서드로서 상수를 나타내는 장점은, 프로그램이 커지면서 상수가 몇 가지 다른 특성에 의존하게 되는 경우, 메서드 내부의 값의 변경을 통한 계산등을 위해 현재 값 10 을 쉽게 변경할 수 있습니다.


메서드 2.6 헬퍼 메서드 초기화

SBEGame>>newCellAt: i at: j
  "Create a cell for position (i,j) and add it to my on-screen
  representation at the appropriate screen position. Answer the new cell"
  | c origin |
  c := SBECell new.
  origin := self innerBounds origin.
  self addMorph: c.
  c position: ((i - 1) * c width) @ ((j - 1) * c height) + origin.
  c mouseAction: [self toggleNeighboursOfCellAt: i at: j].


Squeak comment.pngSBEGame>>cellsPerSide 메서드와 SBEGame>>newCellAt:at: 메서드를 추가하십시오.


새로운 선택자selector toggleNeighboursOfCellAt:at:mouseAction:의 철자를 확인하십시오.


메서드 2.6 은 Matrix 에서 게임상의 cell 에 대한 특정 위치(i,j)에 특별히 지정된 새로운 SBECell 로 응답합니다. 마지막 행은 [self toggleNeighboursOfCellAt: i at: j ] 블록이 되도록 새로운 cell 의 mouseAction 을 정의합니다. 실제로, 이 정의는 마우스를 클릭할 때 실행할 callback 동작을 정의합니다. 이 내용에 대응하는 메서드 또한 정의해야 합니다.


메서드 2.7: callback 메서드

SBEGame>>toggleNeighboursOfCellAt: i at: j
  (i > 1) ifTrue: [ (cells at: i - 1 at: j ) toggleState].
  (i < self cellsPerSide) ifTrue: [ (cells at: i + 1 at: j) toggleState].
  (j > 1) ifTrue: [ (cells at: i at: j - 1) toggleState].
  (j < self cellsPerSide) ifTrue: [ (cells at: i at: j + 1) toggleState].


메서드 2.7은 게임상 (i,j) cell 의 네 방향에 있는 4개의 칸 상태를 토글합니다. 유일한 문제가 있다면 보드의 크기는 유한하기 때문에, 사용자가 cell 의 상태를 토글 하기 전에, 이웃한 cell 이 존재할지에 대해 철저히 대비를 해두어야 한다는 것입니다.


Squeak comment.pnggame logic이라 불리는 새 프로토콜에 callback 메서드를 배치하십시오.


메서드를 이동하려면, 간단하게 이름을 클릭하고, 새로 만든 프로토콜(그림 2.11)로 끌어다 놓습니다.


그림 2.11 메서드를 프로토콜에 드래그하기


Quinto 게임을 완성하려면, 마우스 이벤트를 다루기 위해 SBEcell 클래스에서 두 개 이상의 메서드를 정의할 필요가 있습니다.


메서드 2.8: 전형적인 setter 메서드

SBECell>>mouseAction: aBlock
   mouseAction := aBlock


메서드 2.8 은 cell 의 mouseAction 변수를 인수로 설정 한 이후에 새 값에 응답합니다. 이처럼 인스턴스 변수의 값을 바꾸는 메서드를 setter 메서드라고 하며, 인스턴스 변수의 현재 값을 응답하는 메서드를 getter 메서드 라고 부릅니다.


독자가 다른 프로그래밍 언어에서 getters 와 setters 를 사용해봤다면, setmouseAction 과 getmouseAction 이라고 하는 메서드를 기대했겠지만, 스몰토크의 표기 관례는 다릅니다. getter 메서드는 변수의 이름과 같은 이름이어야 하며, setter 메서드는 비슷한 이름으로 만들어지지만, 마지막에 ":" 을 붙입니다. 따라서 mouseAction 과 'mouseAction:' 이 됩니다.


정리하자면, setter 와 getter 는 접근자 메서드라고 불리며, 관례상, accessing 프로토콜로 분류됩니다. Smalltalk 에서, 모든 인스턴스 변수는 객체에서 private으로 취급되며, Smalltak 언어에서 다른 객체를 통해 이러한 인스턴스 변수를 읽고 쓰려면, 앞에서 설명한것처럼 접근자 메서드[2]를 통해야 합니다.[1]


Squeak comment.pngSBECell 클래스로 가서, SBECell>>mouseAction: 을 정의하고 accessing 프로토콜에 넣으십시오.


마지막으로 메서드 mouseUp:을 정의해야 하며, 이 메서드는 화면의 칸 위에 마우스가 머무는 동안 마우스 버튼을 떼면, GUI 프레임워크에서 자동으로 호출될 것입니다.


메서드 2.9 이벤트 핸들러

SBECell>>mouseUp: anEvent
mouseAction value


Squeak comment.pngSBECell>>mouseUp: 메서드를 추가하고, 메서드를 categorize all uncategorized 하십시오.


이 메서드는 인스턴스 변수 mouseAction에 저장한 객체로 value 메시지를 보내서 처리하도록 동작합니다. 사용자가 SBEGame>>newCellAt: i at: 에서 mouseAction 에 인자로 대입한 다음의 코드가 다시 호출됩니다:

[self toggleNeighboursOfCellAt: i at: j ]

value 메시지를 보내면, 해당되는 코드부분이 실행되며 cell 의 상태를 전환합니다.


Notes

  1. 1.0 1.1 squeak vm 상에서 작동되는 squeak image 를 의미합니다 Cite error: Invalid <ref> tag; name "역자주1" defined multiple times with different content
  2. 사실 하위클래스에서는 접근이 가능합니다