SqueakByExample:9.6
컬렉션 사용에 대한 몇 가지 힌트
add: 메서드를 사용할 때 발생되는 일반적인 실수: 다음의 에러는 가장 많이 발생되는 스몰토크 코딩에서의 실수 중 하나 입니다.
collection := OrderedCollection new add: 1; add: 2.
collection ⇒ 2
여기서 보게되는 변수 collection 은 새롭게 만들어진 컬렉션이 아니라, 마지막에 추가된 숫자를 보관합니다. 왜냐하면 메서드 add: 는 추가된 요소를 반환하되, 수신자는 반환하지 않기 때문입니다.
다음 코드에서 예상대로의 결과를 얻을 수 있습니다:
collection := OrderedCollection new.
collection add: 1; add: 2.
collection ⇒ an OrderedCollection(1 2)
그외에 yourself 메시지를 사용할 수 있는데, 이 메시지는 cascade 된 메시지의 수신자를 반환합니다.
collection := OrderedCollection new add: 1; add: 2; yourself ⇒ an OrderedCollection(1 2)
반복을 수행하고 있는 콜렉션으로부터 요소를 삭제. 자주 일어날 수 있는 또 다른 실수는, 현재 반복작업을 수행하는 컬렉션으로부터 요소를 제거하는 것입니다. remove: 를 이용하는 경우에 말이죠.
range := (2 to: 20) asOrderedCollection.
range do: [:aNumber | aNumber isPrime ifFalse: [ range remove: aNumber ] ].
range ⇒ an OrderedCollection(2 3 5 7 9 11 13 15 17 19)
9 와 15 가 걸러져야 했기 때문에, 이 결과는 잘못된 결과입니다.
해결 방법은, 검사를 하기 전에 컬렉션을 복사해 두는 것입니다.
range := (2 to: 20) asOrderedCollection.
range copy do: [:aNumber | aNumber isPrime ifFalse: [ range remove: aNumber ] ].
range ⇒ an OrderedCollection(2 3 5 7 11 13 17 19)
= 와 hash 는 한번에 양쪽 모두 재정의 되어야 한다. 에러중 발견하기 어려운 경우는, 사용자가 = 을 재정의하면서 hash 는 재정의하지 않는 경우입니다. 이런경우 Set 에 분명히 넣은 요소가 어느새 없어진다는 현상등이 나타납니다. Kent Beck 이 제안한 해결책은 xor: 을 이용해서 bash를 재정의 하는 것입니다. 예를 들어, 만약 제목과 저자가 같은경우, 두 개의 책을 동일한 것으로 판단하고 싶을때, 다음과 같이 = 를 재정의할 뿐만 아니라 hash도 재정의 해야 할 것입니다.
메서드 9.1 = 과 hash 재정의 하기
Book»= aBook
self class = aBook class ifFalse: [↑ false].
↑ title = aBook title and: [ authors = aBook authors]
Book»hash
↑ title hash xor: authors hash
만약 Set 의 요소 또는 Dictionary 에 대한 key 를, 그 자체의 hash 값의 변경이 가능한 객체처럼-수정가능한 객체를 사용하는 경우에는, 또 다른 끔찍한 문제가 발생합니다. 당신이 디버깅을 정말로 좋아하는게 아니라면, 이런 경우에는 수정가능한 객체를 사용하지 말아주세요!