Skip to main content
Engineering LibreTexts

2.07: Organizing Methods into Protocols

  • Page ID
    37587
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)

    Before we define any more methods, let’s take a quick look at the third pane at the top of the browser. In the same way that the first pane of the browser lets us categorize classes so we are not overwhelmed by a very long list of class names in the second pane, so the third pane lets us categorize methods so that we are not overwhelmed by a very long list of method names in the fourth pane. These categories of methods are called “protocols”.

    If there are only a few methods in a class, the extra level of hierarchy provided by protocols is not really necessary. This is why the browser also offers us the --all-- virtual protocol, which, you will not be surprised to learn, contains all of the methods in the class.

    Categorize all uncategorized methods.
    Figure \(\PageIndex{1}\): Categorize all uncategorized methods.

    If you have followed along with this example, the third pane may well contain the protocol as yet unclassified.

    \(\bigstar\) Select the yellow button menu item categorize all uncategorized to fix this, and move the initialize methods to a new protocol called initialization.

    How does Squeak know that this is the right protocol? Well, in general Squeak can’t know, but in this case there is also an initialize method in a superclass, and Squeak assumes that our initialize method should go in the same category as the one that it overrides.

    You may find that Squeak has already put your initialize method into the initialization protocol. If so, it’s probably because you have loaded a package called AutomaticMethodCategorizer into your image.

    A Typographic Convention.

    Smalltalkers frequently use the notation “>>” to identify the class to which a method belongs, so, for example, the cellsPerSide method in class SBEGame would be referred to as SBEGame>>cellsPerSide. To indicate that this is not Smalltalk syntax, we will use the special symbol \(\gg\) instead, so this method will appear in the text as SBEGame\(\gg\)cellsPerSide.

    From now on, when we show a method in this book, we will write the name of the method in this form. Of course, when you actually type the code into the browser, you don’t have to type the class name or the \(\gg\); instead, you just make sure that the appropriate class is selected in the class pane.

    Now let’s define the other two methods that are used by the SBEGame\(\gg\)initialize method. Both of them can go in the initialization protocol.

    Code \(\PageIndex{1}\) (Squeak): A Constant Method

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

    This method could hardly be simpler: it answers the constant 10. One advantage of representing constants as methods is that if the program evolves so that the constant then depends on some other features, the method can be changed to calculate this value.

    Code \(\PageIndex{2}\) (Squeak): An Initialization Helper Method

    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].
    

    \(\bigstar\) Add the methods SBEGame\(\gg\)cellsPerSide and SBEGame\(\gg\)newCellAt:at:.

    Confirm the spelling of the new selectors toggleNeighboursOfCellAt:at: and mouseAction:.

    Code \(\PageIndex{2}\) answers a new SBECell, specialized to position (i, j) in the Matrix of cells. The last line defines the new cell’s mouseAction to be the block [self toggleNeighboursOfCellAt: i at: j ]. In effect, this defines the callback behaviour to perform when the mouse is clicked. The corresponding method also needs to be defined.

    Code \(\PageIndex{3}\) (Squeak): The Callback Method

    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].
    

    Code \(\PageIndex{3}\) toggles the state of the four cells to the north, south, west and east of cell (i, j). The only complication is that the board is finite, so we have to make sure that a neighboring cell exists before we toggle its state.

    \(\bigstar\) Place this method in a new protocol called game logic.

    To move the method, you can simply click on its name and drag it to the newly-created protocol (Figure \(\PageIndex{2}\)).

    Drag a method to a protocol.
    Figure \(\PageIndex{2}\): Drag a method to a protocol.

    To complete the Quinto game, we need to define two more methods in class SBECell to handle mouse events.

    Code \(\PageIndex{4}\) (Squeak): A Typical Setter Method

    SBECell»mouseAction: aBlock
        ↑ mouseAction := aBlock
    

    Code \(\PageIndex{4}\) does nothing more than set the cell’s mouseAction variable to the argument, and then answers the new value. Any method that changes the value of an instance variable in this way is called a setter method; a method that answers the current value of an instance variable is called a getter method.

    If you are used to getters and setters in other programming languages, you might expect these methods to be called setmouseAction and getmouseAction. The Smalltalk convention is different. A getter always has the same name as the variable it gets, and a setter is named similarly, but with a trailing “:”, hence mouseAction and mouseAction:.

    Collectively, setters and getters are called accessor methods, and by convention they should be placed in the accessing protocol. In Smalltalk, all instance variables are private to the object that owns them, so the only way for another object to read or write those variables in the Smalltalk language is through accessor methods like this one.1

    \(\bigstar\) Go to the class SBECell, define SBECell\(\gg\)mouseAction: and put it in the accessing protocol.

    Finally, we need to define a method mouseUp:; this will be called automatically by the GUI framework if the mouse button is released while the mouse is over this cell on the screen.

    Code \(\PageIndex{5}\) (Squeak): An Event Handler

    SBECell»mouseUp: anEvent
        mouseAction value
    

    \(\bigstar\) Add the method SBECell\(\gg\)mouseUp: and then categorize all uncategorized methods.

    What this method does is to send the message value to the object stored in the instance variable mouseAction. Recall that in SBEGame\(\gg\)newCellAt: i at: j we assigned the following code fragment to mouseAction:

    [self toggleNeighboursOfCellAt: i at: j ]

    Sending the value message causes this code fragment to be evaluated, and consequently the state of the cells will toggle.


    1. In fact, the instance variables can be accessed in subclasses too.


    This page titled 2.07: Organizing Methods into Protocols is shared under a CC BY-SA 3.0 license and was authored, remixed, and/or curated by Andrew P. Black, Stéphane Ducasse, Oscar Nierstrasz, Damien Pollet via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.