Smalltalk at Altlang 2008
Transcript of Smalltalk at Altlang 2008
스몰토크(스퀵) 맛보기대안언어축제 튜토리얼
강사: 달룟
때: 2008 11.27~29
소개
스몰토크의 분류객체지향
동적자료형
대소문자 구분
가상머신
바이트코드
GC(쓰레기청소)
순수 객체지향
객체가 아닌 것이 없다.
모든 동작은 메시지를 객체에 보냄으로써
모든 것이 객체
일반적으로 다른 언어에서 객체가 아닌 것이 스몰토크에서는 객체다.
기본 자료형: int, double, char
클래스
개발툴, 프로세스, 컴파일러, 가상머신
메서드, 메시지
동적 자료형
변수 선언할 때, 자료형을 명시하지 않는다.
변수에는 어떠한 것이든 대입할 수 있다.
myFriend := ‘peter’.myFriend := 18.myFriend := Object new.
이미지 기반
Snapshot
VMWare, Virtual PC 같다.
소스파일은 필요없다.
lib, header, source 경로 설정 필요없다.
개발환경을 통채로 전달할 수 있다.
모든 동작은 메시지 보내기로 한다는 것
객체를 사용하는 사람은 그 객체가 무엇을 할 수 있을 지 모르는 상태에서 명령을 한다(메시지를 보낸다).
객체는 그 메시지를 이해할 수도 이해하지 못할 수도 있다.
메시지의 실행은 객체의 클래스와 그 상위클래스에 있는 메서드 사전을 찾아보고 판단
실행하면서 코딩한다.
엔진실 응답하라. 계측기가 완성될 때까지, 속도를 계속 유지하고 펌프를 계속 가동시켜라.
시범: 실행하면서 코딩한다.
• 여러 개의 Flasher를 화면에 띄운다.
• 클래스 브라우저에서 상위클래스를 RectangleMorph로 바꾼다.
• 인스턴스 변수offColor를 추가하고, 반짝임을 “onColor와 어둡게한 onColor”가 아니라, “onColor offColor 교대로 쓰게” 바꾸자.
코드가 실행되면 그곳에는 객체가 있다.
void리턴이 없다.
반드시 리턴값이 있다.
스몰토크의 모든 것은 객체다.
따라서, 모든 부분 코드(표현)는 객체로 간주할 수 있다.
나쁜 것은 금지, 좋은 것은 강제
public member variable
설계에 시간소모
언제나 통합
스몰토커는 구글을 쓰지 않아!
코딩하다 말고 구글링을 하는 이유
API가 바이너리라서 사용법을 공부해야 한다. ☞☞ 코드가 모두 노출
에러가 발생했는데, 이유를 알 수 없다. ☞☞ 코드가 모두 노출
무언가 하려고 하는데, 예제가 없다. ☞☞ 맘만 먹으면 따라할 수 있다
기본 사용법
웍스페이스 Workspace
do it
선택한 영역을 실행한다
cmd + d
팝업메뉴에서
print it
선택한 영역을 실행하여 리턴된 객체를 보여준다.
cmd + p
팝업메뉴에서
printString 메서드
inspect it
선택한 영역을 실행하여 리턴된 객체를 보여주는 인스펙터를 연다
cmd + i
팝업메뉴에서
inspect 메서드
인스펙터 inspector
변수들 상세정보
W.S
.
explore it
선택한 영역을 실행하여 리턴된 객체를 보여주는 익스플로러를 연다
cmd + I
팝업메뉴에서
explore 메서드
익스플로러 explorer
트리
W.S.
트리에서선택한 객체가self가 된다구!
debug it
선택한 영역을 실행하는 과정을 디버거로 보여준다
단축키 없음
팝업메뉴에서
디버거 Debugger
스택
소스코드
제어버튼
객체변수
객체
WS
인자
,임시
통합
WS
browse it
어떤 클래스에 관한 모든 소스코드를 본다.
스몰토크 프로그래밍의 중심 도구
cmd + b
많은 도구들에 메뉴가 제공되고 있다
브라우저 Browser
분류기
소스코드
버튼
카테고리
클래스
M Cat.
메서드
문법
리터럴 Literal 영어사전: “있는 그대로”예
42123.451.2345e22r10010010$A‘Smalltalk string’#symbol#(1 2 3 4)[ a + b ]
객체와 클래스
모든 객체는 클래스의 인스턴스
모든 클래스는 부모클래스가 있다
Object가 뿌리 클래스
특수 변수self
super
true
false
nil
thisContext (스퀵에서만)
대입 불가능
언제나 존재
모든 동작은 메시지로
(메시지를 받는 객체) (메시지) (인자들)
메시지가 먼저 나오는 경우는 절대 없다.
문장은 처음은 반드시 객체
3 종류의 메시지
인자없는 메시지(unary message)
연산자형 메시지(binary message)
인자있는 메시지(keyword message)
인자없는 메시지Unary Message
morph open.
$A asciiValue
Integer superlcass
연산자형 메시지Binary Message
1+2
1=2
1==2
1 -> 2
1 @ 2
인자있는 메시지Keyword Message
10 to: 20
‘hello altlang’ at: 5
3 between: 1 and: 5
Color r: 0.4 g: 0.7 b: 0.1
마치 한국어 같은 인자있는 메시지
조사(전치사) 있다.
철수야, 사과를 상자에 조심스럽게 넣어라.
cholsu.putItInto(apple, box, CAREFULLY);
cholsu put: apple into: box how: #carefully
우선순위널리쓰이는 다음의 우선순위는 무시
* / 이 + - 보다 높다
==가 다른 연산자보다 낮다
메시지 종류에 따른 우선순위
인자없는 > 연산자형 > 인자있는
소괄호를 써서 실행순서를 명시할 수 있다.
스몰토크의 낯선 우선순위 때문에 생기는 실수
• 다음을 실행하면 어떤 일이 벌어질까?
• 3 + 4 * 5
• 3 < 4 + 2
• 4 + 5 sqrt
• 4 max: 3 + 2
• 의도대로 하려면, 에러가 발생하지 않게 하려면 어떻게 해야 할까?
주석
겹따옴표(“”)로 둘러쌓인 영역은 주석으로 실행되지 않는다.
행 주석은 없다.
1 “one” + “plus” 2 “two”
1 + 2
마침표(.)
문장의 끝임을 나타내는 문자
두 개 이상은 문장이 연속 실행될 때 문장과 문장을 구분한다.
한 문장을 여러 줄에 걸쳐서 작성할 수 있다!
World canvas fillColor: Color red.Display restore.20 + 3.
세미콜론(;)
연속된 문장의 주어객체(receiver)가 같을 때, 주어객체의 언급을 생략할 수 있게 한다.
myObj doWork1.myObj add: 1.myObj doWork2.
myObj doWork;add: 1; doWork2
리턴 기호 ^
^로 시작하는 문장의 실행결과가 되돌려진다.
이하 코드는 실행되지 않는다.
↑
void리턴이 없다
리턴을 하지 않으면 self가 자동 리턴된다.
^self
코드(표현)이 실행되면 그곳에는 객체가 남는다.
대입
a := 3.b := 4.c := a+b.
:= _
a _ 3.b _ 4.c _ a+b.
a ← 3.b ← 4.c ← a+b.
a := 3.b := 4.c := a+b.
블록
리터럴 중 하나
참았다가 실행하는 객체
suspend상태로 생성된 쓰레드와 비슷
하나 이상의 문장을 포함할 수 있음
마지막 문장의 값이 블록의 값
블록
[ ]
[ daliot join: party. altlang add: party ]
[ | pos | pos := altlang location. pos nation ]
[ :person :party | party includes: person ]
[ :x| | y | y := x * x ]
실습: 블록은 참았다가 실행하는 객체
• a := 10.bl := [ a:= 0 ].a. “이 때 a의 값은 얼마일까?”bl value.a “이 때 a의 값은 얼마일까?”
실습: 블록은 간이 메서드
• 다음을 실행했을 때, 공은 어느 컵에 있을까요?
• cups := #(nil ball nil).m1 := [cups swap: 1 with: 2].m2 := [cups swap: 2 with: 3].m3 := [cups swap: 1 with: 3].
m2 value.m3 value.m1 value.m2 value.m3 value.cups.
• 그 공을 원래 위치로 놓으려면 어느 블록에 #value 를 해야 할까요?
실습: 블록은 유연한 설계의 수단
• 문자열 ‘alonzo’ ‘seal’ ‘morning’ 을 세 가지 기준으로 정렬하라.
• 알파벳 순서
• 길이 순서
• 문자 o의 개수
변수의 종류임시 변수
인스턴스 변수
전역 변수
클래스 변수
클래스 인스턴스 변수
공유 사전(pool dictionary)
임시 변수
| 변수들 |
소문자로 시작
| pig cow total |pig := 3.cow := 4.total := pig+cow.
인스턴스 변수멤버변수 혹은 필드라고 부르는 바로 그것
객체마다 값이 다를 수 있는 변수
소문자로 시작
클래스 정의에 포함
PasteUpMorph subclass: #ZoomAndScrollMorph! instanceVariableNames: 'sourceRectangle usingBalloon panAndTiltFactor zoomFactor'! classVariableNames: ''! poolDictionaries: ''! category: 'MorphicExtras-Demo'
전역변수
대문자로 시작
선언문 없음
대입을 하면, 자동으로 생성 됨(경고문)
Smalltalk at:
Smalltalk at: put:
클래스 변수대문자로 시작
클래스 정의문에 선언된다
클래스와 인스턴스가 접근할 수 있다.
상위클래스는 접근할 수 없다.
Object subclass: #AsyncFile! instanceVariableNames: 'name writeable semaphore fileHandle'! classVariableNames: 'Busy ErrorCode'! poolDictionaries: ''! category: 'Files-Kernel'
클래스 인스턴스 변수
대문자로 시작
클래스 정의문에 선언된다
클래스와 인스턴스가 접근할 수 있다.
클래스 자신과 하위클래스 모두 변수가 생긴다. 각 클래스마다 자신만의 변수를 소유
공유 사전(pool dictionary)
대문자로 시작
클래스 정의문에 선언된다
클래스와 인스턴스가 접근할 수 있다.
정체는 Dictionary인데, 사용한다고 선언하면, 그때부터는 그것의 키가 변수처럼 사용된다.
괄호
( ) paranthsis 소괄호 표현계산 우선순위
[ ] block 블록 실행될 수 있는 코드 뭉치
{ } curly braces 중괄호표현식의 나열로 배열을 만든다(스퀵에서만 쓰임)
메서드 정의머리, 임시 변수 선언, 몸통으로 이루어짐
머리는 sigature라고 불리며, 메서드의 이름과 인자들의 이름이 나타난다.
임시 변수 선언은 머리 다음에서만
몸통에는 문장들이 있으며, 마침표(.)로 구분되어 순서대로 실행된다.
하나 이상의 리턴 ^
메서드는 이렇게 생겼다exampleWithNumber: x
“This is a small method that illustrates every part of Smalltalk method syntax except primitives, which aren’t very standard. It has unary, binary, and key word messages, declares arguments and temporaries (but not block temporaries), accesses a global variable (but not and instance variable), uses literals (array, character, symbol, string, integer, float), uses the pseudo variable true false, nil, self, and super, and has sequence, assignment, return and cascade. It has both zero argument and one argument blocks. It doesn’t do anything useful, though”
| y | true & false not & (nil isNil) ifFalse: [self halt]. y := self size + super size. #( $a #a ‘a’ 1 1.0) do: [: each | Transcript show: (each class name); show: (each printString); show: ‘ ‘]. ^ x < y
주석인자특수변수임시변수클래스블록변수
소스코드에서 객체를 알아보는 방법
표현의 시작은 반드시 객체다.
다음 기호들 뒤에 따라 나오는 것은 객체
비법
:= 대입기호^ 리턴기호. 문장구분: 콜론
( [ { 괄호
소스코드에서 메서드를 알아보는 방법
객체 뒤에 따라오는 것은 모두 메서드
콜론(:)으로 끝나는 낱말은 모두 메서드의 일부분
비법
다음의 스몰토크 코드에서 객체와 메서드를 찾아라
writeIHDRChunkOn: aStream "Write the IHDR chunk" aStream nextPutAll: 'IHDR' asByteArray. aStream nextInt32Put: width. aStream nextInt32Put: height. aStream nextNumber: 1 put: bitsPerChannel. aStream nextNumber: 1 put: colorType. aStream nextNumber: 1 put: 0. "compression" aStream nextNumber: 1 put: 0. "filter method" aStream nextNumber: 1 put: 0. "interlace method"
다음의 스몰토크 코드에서 객체와 메서드를 찾아라
writeIHDRChunkOn: aStream "Write the IHDR chunk" aStream nextPutAll: 'IHDR' asByteArray. aStream nextInt32Put: width. aStream nextInt32Put: height. aStream nextNumber: 1 put: bitsPerChannel. aStream nextNumber: 1 put: colorType. aStream nextNumber: 1 put: 0. "compression" aStream nextNumber: 1 put: 0. "filter method" aStream nextNumber: 1 put: 0. "interlace method"
객체메서드
다음의 스몰토크 코드에서 객체와 메서드를 찾아라
evaluateSelection "Treat the current selection as an expression; evaluate it and return the result" | result rcvr ctxt | self lineSelectAndEmptyCheck: [^ ''].
(model respondsTo: #doItReceiver) ifTrue: [FakeClassPool adopt: model selectedClass. "Include model pool vars if any" rcvr _ model doItReceiver. ctxt _ model doItContext] ifFalse: [rcvr _ ctxt _ nil]. result _ [ rcvr class evaluatorClass new evaluate: self selectionAsStream in: ctxt to: rcvr notifying: self ifFail: [FakeClassPool adopt: nil. ^ #failedDoit] logged: true. ] on: OutOfScopeNotification do: [ :ex | ex resume: true]. FakeClassPool adopt: nil. ^ result
다음의 스몰토크 코드에서 객체와 메서드를 찾아라
evaluateSelection "Treat the current selection as an expression; evaluate it and return the result" | result rcvr ctxt | self lineSelectAndEmptyCheck: [^ ''].
(model respondsTo: #doItReceiver) ifTrue: [FakeClassPool adopt: model selectedClass. "Include model pool vars if any" rcvr _ model doItReceiver. ctxt _ model doItContext] ifFalse: [rcvr _ ctxt _ nil]. result _ [ rcvr class evaluatorClass new evaluate: self selectionAsStream in: ctxt to: rcvr notifying: self ifFail: [FakeClassPool adopt: nil. ^ #failedDoit] logged: true. ] on: OutOfScopeNotification do: [ :ex | ex resume: true]. FakeClassPool adopt: nil. ^ result
객체메서드
블록은 객체다
끝~~ ^^
if는?
while은?
switch는? for는?
배열은?
연산자는?
자료형은?
생성자는?
파괴자는?
new는?
다 라이브러리야! ^^
자료형은...
3.14 class
‘hello world’ class
1004 class
다 라이브러리야! ^^
true class
false class
if는...진리값(Boolean)객체의 메서드
복잡한 표현식 ifTrue: [ 표현식이 참일 때 실행될 표현 ]
다 라이브러리야! ^^
ifFalse: 라는 것도 있음
실습: 루비의 후위 if를 구현하자
• 루비의 후위 if는 영어 가정법 문장과 같은 꼴
• 자연스럽게 읽히는 장점
• x>10 ifTrue: [ x := x-5 ] 를
• [ x := x-5 ] if x>10 로
while은...다 라이브러리야! ^^
블록객체의 메서드일 뿐
[ x = 1 ] whileFalse: [ x := x // 2 ].
[ str size < 100 ] whileTrue: [ str := str , str ].
실습: 무한루프 방지 while 문
• while문은 자칫 무한루프로 빠지기 쉽다
• 무한루프에 빠질 것 같으면, 중단시키는 while문이 있다면 좋지 않을까?
• x := 10.[ x > 0 ] whileTrue: [ x := x / 2 ] 를
• x := 10.[ x > 0 ] whileTrue: [ x := x / 2 ] loopLimit: 100 로 바꾸자
for은...다 라이브러리야! ^^
(1 to: 10) do: [:num|
Transcript show: num ; show: ‘ little indian boy’; cr ]
Interval 객체, #do: 를 쓴다.
switch는...
없다!
다형성 (Polymorphism, 多形性)으로
if + return 으로
다 라이브러리야! ^^
연산자는...
메서드다!
사칙연산 +, - , *, /가 Number, Integer, Float클래스에 메서드로 정의되어 있다.
다 라이브러리야! ^^
배열은...
Array 클래스의 객체
배열첨자접근연산자([])같은 것은 없고,
#at: , #at:put: 메서드로 대신한다.
다 라이브러리야! ^^
new는...
클래스의 메서드
클래스가 new라는 메시지를 받으면, 객체를 만들어 리턴한다.
다 라이브러리야! ^^
생성자는...
따로 없다.
initialize라는 것이 있긴한데, 반드시 정의해줘야 하거나, 반드시 불린다거나하는 보장은 없다.
initialize가 불리는 이유는 new메서드에서 불리기 때문
다만, 스퀵에서는 initialize가 반드시 불린다.
다 라이브러리야! ^^
파괴자는...
따로 없다.
finalize라는 것이 있긴 한데, 이것도 반드시 불리는 것은 아니다.
beFinalizable 를 당했을 때만 불린다.(돌핀)
스퀵은? 모름...
다 라이브러리야! ^^
물고기 잡는 법
스몰토크를 공부하는 마음가짐
몰라도 괜찮다. 탐험하듯이
분해하기 전에, 먼저 써보자.
봤노라. 찾았노라. 고쳤노라
소스코드를 뒤적이며 스스로 터득
senders of it
어떤 메서드가 사용된 모든 메서드를 찾는다
어떤 메서드의 사용법을 공부할 때
cmd + n
W.S.의 메뉴
메서드 목록의 메뉴
implementers of it
어떤 이름의 메서드가 정의된 모든 경우를 찾는다.
다형성을 확인
cmd + m
W.S. 의 메뉴
메서드 목록의 메뉴
Class refs
어떤 클래스가 쓰이는 메서드를 모두 찾는다.
클래스의 사용법을 알 수 있다. (특히 객체생성법)
클래스 브라우저의 메뉴
문자열로 찾아라
코드를 찾는 가장 쉬운 방법
cmd + E
단점: 검색결과가 많으면 어느 것이 실행되는지 알 수 없다.
실습: 색깔 바꾸는 메서드를 찾아라
• 모프의 색깔을 바꾸는 메서드를 찾아보자.
• 힌트: 할로버튼의 도움말풍선
• 웍스페이스에서 찾은 코드를 실행해보자.
디버거를 활용하자
코드의 실행순서나 코드의 구조를 이해하려 할 때, 디버거를 쓰면 쉽게 이해된다.
메시지 영역 확인
변수값 확인
다른 메서드의 소스코드 확인
다른 언어에서 디버거는 무섭다!
메모리 주소
어셈블리코드
낮은 레벨의 CPU상태
내 객체들은 어디에?
답이 없으면 메뉴얼이 only hope
스몰토크의 디버거는 귀엽다
거의 항상 소스코드 보임
모두 객체뿐
높은 수준의 추상화
중첩 디버깅
실습: 1/100 가 어떻게 계산되는지 지켜보자
• 1/100을 아무데나 친다.
• 팝업메뉴로 debug를 고른다.
• 디버거가 뜨면 into 버튼을 여러 번 눌러보자.
인스펙터로 메서드 짜기
해당 객체를 인스팩터로 연다.
인스팩터로 이런 저런 실행코드를 작성해본다.
실행이 잘 되면, 그 코드를 그대로 메서드를 작성해 준다.
실습: FlasherMorph >> dodo
• FlashMorph를 띄운다.
• 인스펙터를 연다
• 인스펙터에서 코드를 만들어보자.
• 실행에 성공한 코드를 dodo라는 메서드로 만든다.
• dodo를 실행하자.
Method Finder
입출력
결과
설명
메서드
실습: 메서드를 찾자
• 음수를 양수로 바꾸는 메서드는 무엇일까?
• 최대공약수를 찾는 메서드는 무엇일까?
• 문자열을 이어붙이는 메서드는 무엇일까?
• 배열의 크기를 구하는 메서는 무엇일까?
perform:
obj1 copy
obj1 perform: #copy
perform:
10 + 5
10 perform: #+ with: 5
perform:
obj1 with: 1 say: ‘hello’ after: obj2
obj1 perform: #with:say:after: withArguments: (Array with: 1 with: ‘hello’ with: obj2)
실습: perform:
• obj1 := 3.obj2 := 'Smalltalk'.
sel1 := #at:sel2 := #raisedTo:
arg1 := 4.arg2 := 2.
• 가능한 모든 조합의 perform:을 해보자.obj1 perform: sel1 with: arg1.obj1 perform: sel1 with: arg2.obj1 perform: sel2 with: arg1.obj1 perform: sel2 with: arg2.obj2 perform: sel1 with: arg1.obj2 perform: sel1 with: arg2.obj2 perform: sel2 with: arg1.obj2 perform: sel2 with: arg2.
만만한 게 메뉴와 버튼메뉴와 버튼 모프에는
메시지를 받을 객체 target
보낼 메시지 action
인자 arguments
가 들어 있다
인스펙터로 확인하자!
doButtonAction
실습: Watch(시계)에서 로마숫자표기 기능 배우기
• Watch모프는 시간표시 숫자를 로마자로 표시하는 기능이 포함되어 있다.
• Watch로부터 숫자를 로마숫자로 표시하는 메서드를 찾아라.
• 인스펙터로 실행해 보자.
• 디버거로 속을 들여다 보자.
#halt
멈춤점(break point)
객체에 #halt 메시지를 보내면, 실행이 멈춘다.
디버거 작동
주의: 바쁘게 동작하는 객체에 걸면 곤란해 짐
실습: 클립보드 해킹
• Clipboard 모프를 연다.
• 이 모프의 step메서드를 열어 보자.
• self halt 를 걸어보자.
• cmd + c 혹은 copy메뉴로 텍스트복사를 하고, step에서 벌어지는 일을 디버거로 지켜보자.
• Clipboard 클래스를 쓰는 법을 깨달았다면, 응용해보자.
날린 코드 복구하기
이미지 저장하지 않으면 모든 것을 잃는다.
스몰토크는 실행하거나 컴파일한 모든 것을 .changes 파일에 항상 기록하고 있다.
File List 로 .changes 파일을 열면 그 내용을 복구할 수 있다.
간단한 실습 ^^
도전!!
실습: 구구단
• 구구단
• for 2개로 짤 수도 있겠지만...
• #(1 2 3 4 5 6 7 8 9) * 1#(1 2 3 4 5 6 7 8 9) * 2#(1 2 3 4 5 6 7 8 9) * 3#(1 2 3 4 5 6 7 8 9) * 4
솟수(prime number)
2~N 사이의 모든 솟수(prime number)를 구하라
에라토스테네스의 체
배울 수 있는 것들
배열의 사용법, collect:, select:의 사용법
변수 대입, 나머지, 블록
실습: 2~N 사이의 모든 솟수를 구하라
• 2, 3, 4, 5, ... , 18, 19, 20의 배열을 만든다.
• 2를 솟수로 등록한다
• 2로 나누어 떨어지는 수는 모두 버린다.
• 3을 솟수로 등록한다
• 3으로 나누어 떨어지는 수는 모두 버린다.
• ... 반복 ...
실습: 대소문자 뒤집기
• 문자열의 대문자는 소문자로, 소문자는 대문자로 바뀐 문자열을 생성하는 메서드를 만들자.
• 'Smalltalk is born from Palo Alto LAB' caseReversed 하면...
• 'sMALLTALK IS BORN FROM pALO aLTO lab' 가 만들어지도록
실습: isRedundant 메서드 만들기
• 배열의 모든 객체들이 한 번만 등장하는 지 확인하는 메서드
• ‘abc’ isRedundant --> false
• ‘abca’ isRedundant --> true
• #(3 3 3) isRedundant --> true
• #(10 20 30) isRedundant --> false
실습: 모프 감추기 그리고 보이기
• 아무 모프나 인스펙터로 연다.
• 그 인스펙터에서 self 에 hide 메시지를 보내본다.
• show 메시지를 보내본다.
• 도전: 모든 모프를 hide시켜보자. 또, show 시켜보자.
• 힌트: allSubInstances
버튼: target, action, arguments
SimpleButtonMorph
버튼에는 target(model), action, arguments가 들어있다.
버튼이 눌리면,target perform: action withArguments: arguments가 실행된다.
실습: 창 닫는 버튼 만들기
• 모프 객체의 인스펙터를 연다.
• 인스펙터에서 SimpleButtonMorph 객체를 만들되, 그것의 target, action, arguments를 잘 지정한다.
• 버튼을 눌러본다.
• 힌트: 창닫는 메시지 delete
실습: TextMorph 내용 바꾸는 버튼 만들기
• TextMorph 객체를 만든다.
• 이 모프의 인스펙터를 연다.
• 인스펙터에서 SimpleButtonMorph 객체를 만들되, 그것의 target, action, arguments를 잘 지정한다.
• 버튼을 눌러본다.
• 힌트: contents:
실습: TextMorph 내용 뒤집는 버튼 만들기
• TextMorph 객체를 만든다.
• 이 모프의 인스펙터를 연다.
• 인스펙터에서 SimpleButtonMorph 객체를 만들되, #reverseContents 가 actionSelector로 되도록 한다.
• 버튼을 눌러본다.
실습: Big Bang
• 모프의 영역을 바꾸는 메서드를 알아내자. (힌트: 인스펙터)
• 모프의 영역을 좁게 만드는 문장을 만들자.
• 모프의 영역을 넓게 만드는 문장을 만들자.
• 두 문장을 번갈아 실행 해보자.• 욕심: 두 동작을 하는 버튼을 만들 수 있을까?
실습: 빠르게 자라는 숲
• Trees 객체를 여러 개 만든다.
• 나무 그림을 초기화하는 메서드를 알아낸다.
• 나무 그림을 완성하는 메서드를 알아낸다.
• 모든 Trees 모프에게 위에서 알아낸 메서드를 불러준다.
• 배경색을 투명하게 바꾸자.(힌트) Color black을 찾자
실습: 부풀어 오르는 풍선
• 0.1초 마다 조금씩 커지는 풍선을 만들자
• EllipseMorph를 상속 받은 클래스를 하나 만들자.
• 인스펙터로 실행해보면서 적절한 코드를 찾아보자.
• step, stepTime
• 너무 커지거나 클릭 당하면 팡 터지게!!
• 욕심: 풍선은 작을 때는 불투명하지만, 클 때는 속이 비춰 보인다.
실습: 색 뽑기 만들기
• 마우스 커서가 있는 위치의 픽셀의 색깔을 자신의 색깔로 만드는 모프를 만들자.
• step을 구현
• 알아야 할 것
• 마우스의 위치(돋보기 참고)
• 특정 좌표의 색깔힌트: ColorPickerMorph>>pickColorAt:
• 모프의 색깔 바꾸는 방법
addMorph:
두 모프를 addMorph: 하면, 한 모프가 다른쪽 모프에 종속된다.
상위 모프의 submorphs 배열에 추가
하위 모프의 owner 가 설정
상위 모프 삭제시, 하위 모프 함께 삭제 됨
실습: addMorph:
• m1 := Morph new openInHand.m2 := Morph new openInhand.m1 addMorph: m2.m1 delete.
실습: 춤추는 창들
• Bouncing Atoms 모프를 만든다.
• 익스플로러로 이 모프의 submorphs를 관찰하자.
• 한 원자모프가 열려 있는 다른 창을 addMorph: 한다면?
• 열려있는 다른 창World submorphs
클래스 만들기
스몰토크의 클래스 만들기는 이미 존재하는 클래스에게 아기를 만들라고 말하면 된다.
상위클래스 subclass: #만들클래스이름! instanceVariableNames: 인스턴스변수나열문자열! classVariableNames: 클래스변수나열문자열! poolDictionaries: 풀사전나열문자열! category: 카테고리이름
실습: 100개의 클래스
• MyFoo라는 클래스를 만들자
• MyFoo 의 하위 클래스 100개를 만들자
• 하위 클래스의 이름은 Foo와 숫자
• Foo0, Foo1, Foo2, Foo3, Foo4 , ... , Foo98 , Foo99
• MyFoo클래스를 삭제하자
실습: do it 의 정체를 밝혀라!
• “do it” 메뉴로부터 디버깅에 들어간다.
• step into 버튼으로 속으로 속으로 들어가 보자.
• 두 개의 클래스를 찾으면 성공!
• C로 시작하는 클래스
• P로 시작하는 클래스
실습: 줄줄이 돋보기
• Rows 모프를 꺼낸다.
• Magnifier모프를 꺼낸다.
• 그걸 3개 복사해서 Rows모프에 넣는다.
• 4개의 돋보기의 배율을 순서대로 1.5 , 2 , 4 , 8 로 맞춘다.
• 손으로 만든 이 모프를 생성하는 코드를 작성해보자.
숫자야구
두 명의 플레이어가 각자 자기의 비밀수를 결정한다. 비밀수는 0 외 9개의 숫자로 된 4자리의 수다.
한 플레이어가 다른 플레이어에게 4자리 숫자를 물어본다.
다른 플레이어는 그 수를 자신의 비밀수와 비교, 자리와 수가 일치하는 것이 몇개, 자리는 틀리지만 같은 수가 몇개 있다고 답한다.
다른 플레이어가 묻고, 한 플레이어가 답한다.
어느 한 쪽이 비밀수를 맞출 때까지 이것을 반복
실습: 숫자야구
• TestRunner로 단위테스트를 작성하며 모델을 만들자.
• 모프를 만들어 모델을 끼워넣자. (모델의 수정이 필요하다면 고친다)
• 두 사람이서 게임을 해보자.
• 1:1 네트웍 게임으로 만들어보자.
• 서버 클라이언트 다대다 네트웍 게임으로 만들어보자. (아이디와 패스워드)
• 대결 기록을 서버에 남기도록 하자.
• 자동 결투를 하면, 서버가 실력이 비슷한 사람끼리 싸움을 붙이게 하자.
함께
책
Smalltalk-80 ███DP SmalltalkSqueakDolphin Campanionwith styleon toOOD with Multimedia AppBest Practice PatternObjects, and Design
✓✓
✓
제품군
Squeak
Cincom VisualWorks
IBM VisualAge
Dolphin
총본산
www.squeak.org
wiki.squeak.org/squeak
news.squeak.org
methodsandmessages.com.vox.com
프로젝트
map1.squeakfoundation.org/sm
squeaksource.com
opencroquet.org
www.seaside.st
isqueak.org/HomePage
걸음마
www.squeakbyexample.org
www.squeakland.org
www.vimeo.com/groups/squeak
www.iam.unibe.ch/~ducasse/FreeBooks.html
한국
www.squeak.kr
algo.squeak.kr
groups.google.com/group/korean-squeakers