Search code examples
smalltalkpharo

How to change the instance variable of a class in Pharo?


I created a class named Die (singular of Dice) and set an instance variable side.

Object subclass: #Die
    instanceVariableNames: 'side'
    classVariableNames: ''
    package: 'MyPackage'

I initialized the side variable to 6 by default:

initialize

 side := 6. 

However I would like the ability to change the instance variable after the object has been created, like so:

myDie := Die new.
myDie side: 10. " it doesn't to work "

It seems to me that instance variables can only be changed by class methods. Is there a way to change it like above?

Also, I have a method roll that returns a random number between 1 and the specified side. If I create two dice and want to roll two dice at the same time, or maybe three dice at the same time, should I create a different class, something like papercup feed that with the number of dices and implement the roll method on the papercup instead?

Thank you.


Solution

  • You are on a right track. When you execute

    myDie side: 10.
    

    You send a message side: to myDie which is an instance of a class Die. To "respond" to this message, the class die (or its superclasses) should implement a side: method. Ideally, this method is going to look like this:

    side: aNumber
    
        side := aNumber
    

    You see, takes encapsulation very seriously, so instance variables can be directly accessed only by the object itself, and not by anyone from the outside. This is why you always have to create accessors, which is a good practice followed to a various extent by many programming languages.

    Regarding your second question: it's a good idea to have a Papercup class, but if you don't need extensive features, the exact task can be achieved by the following code:

    papercup := OrderedCollection new.
    papercup
        add: die1;
        add: die2;
        add: die3.
    papercup collect: #roll
    

    This way you will roll all the 3 dies and return a collection for 3 numbers (collect: is the same as map() in many programming languages). I provided a shorthand version, whereas the full way to write a collect is: papercup collect: [ :die | die roll] when you specify a complete block (closure) and send the roll message to each die.