3

I'm reading a book on Smalltalk and I have an exercise about the anomaly of disappearing element I'm not able to solve.

Object subclass: Book [
    | isbn |
    <comment: 'A book class'>

    setIsbn: anIsbn [
        isbn := anIsbn.
    ]

    getIsbn [
        ^isbn.
    ]

    = anotherBook [
        ^self getIsbn = anotherBook getIsbn.
    ]
]

| Library |

Library := Set new: 100.
Library add: (Book new setIsbn: '0-671-2-158-1').
(Library includes: (Book new setIsbn: '0-671-2-158-1')) printNl.

I read I have to override the hash method too, but I don't know how to do it. How do I amend the Book class in order to avoid the anomaly?

caisah
  • 1,959
  • 1
  • 21
  • 31

3 Answers3

7

I can't really tell what are you asking about, but to override hash, you should do the same as with =, which you have overridden as well, just by including different definition. So you do something like:

hash [
  "return hash here"
]

If you are asking what hash should be like… well think about it like that: objects that are equal have to have the same hash (but this doesn't have to work the other way around). So I'd suggest you to do something like

hash [
  ^ self getIsbn hash
]

Also about disappearing element. Set is a hashed collection. This means that before comparing it's element with the one you are looking for, it select's a subset by hash. So if you are not overriding hash it may select a subset that won't contain your desired element.

In the end I'd suggest you to use some different implementation of Smalltalk, because my head hurt when I was starting to learn it with . Personaly I use it provides a nice UI and allows you to see what you override, allows you to debug, etc.

Uko
  • 13,134
  • 6
  • 58
  • 106
  • Thanks alot, this was exactly what I was looking for. I didn't know what piece of data I was supposed to hash when I overridden the method. But it makes sense now. – caisah Dec 31 '13 at 15:32
  • 1
    +1 for the #hash override, but I'd have left out the last paragraph, personally. – Frank Shearar Jan 02 '14 at 10:10
  • @FrankShearar yes, you are right. But I don't care. It was really pain for me to program in gnu-smalltalk because you don't know what you have in the image, where is your code etc... Maybe I can help this guy by my last sentence. (Yes, I can recommend other smalltalk dialects, but I don't want to recommend something I'm not sure about) – Uko Jan 02 '14 at 19:46
2

There are a few further Smalltalk idiomatic issues with your code:

  • normally accessors in Smalltalk don't use get and set. So you'd have isbn: anIsbn and isbn.
  • you probably want to create an extra constructor that has the ISBN as a parameter so you don't have to send both new and the setter yourself:

    Book>>onIsbn: anIsbn    
    
        ^self new
             isbn: anIsbn;
             yourself
    
Tobias
  • 3,026
  • 20
  • 34
Stephan Eggermont
  • 15,847
  • 1
  • 38
  • 65
1

The basic rule is never override #= without overriding #hash

Henrik Høyer
  • 1,225
  • 1
  • 19
  • 27