A gentle introduction to classes and methods in Smalltalk
TL;DR
This tutorial illustrates how to turn the Jumble puzzle snippet into a class with methods.
You should have already read A gentle introduction to Pharo Smalltalk.
Introduction
We have seen how to write a snippet that unscrambles a string of characters into a valid English word using an unscrambling dictionary. Now let's see how to turn this code into a class that encapsulates the dictionary and provides an unscrambling method.
The key thing to understand is that programming in Smalltalk consists in making incremental changes to the running system. Each individual change either defines or redefines a class or a method. Each source code change will be logged in the changes file (see Pharo architecture).
Creating a new class
Normally you will create new classes either in the Coder or directly in a Playground Pharo snippet. For example, assuming the Jumble
class does not already exist, the code snippet below will show the name of the class in red, next to a little “quick fix” wrench icon that will allow us to directly create the class. We won't do this, however.
"We can't run this snippet because the class Jumble doesn't exist yet (shown in red). We could 'fix it' by clicking the wrench icon, but instead we will load in the changes from the next snippet below." Jumble new
Instead we will implement our changes directly within the tutorial.
Everything happens by sending messages, and it is the same for creating new classes. We send the message #subclass:...
to the the superclass of the class we want to create. In this case, we ask Object
to create Jumble
as a subclass.
Click on the checkmark to accept this change:
Object subclass: #Jumble instanceVariableNames: 'wordDict' classVariableNames: '' package: 'Tutorial-Jumble'. Jumble class instanceVariableNames: ''
Class comments
It is good practice to always provide a class comment describing the intent and usage of the class, and possibly other details. Let's add a comment:
A Jumble is an object that knows how to unscramble English words: Jumble new unJumble: 'gameses' It encapsulates a dictionary of lists of words, keyed by a sorted string of characters in each word. It unjumbles a word by sorting its characters to form a key and looking up the key in the dictionary.
Initialization
We can create a new Jumble by sending it the unary message new. If we do this and inspect it, we will see in the raw view that its wordDict
is unitialized:
Jumble new
To automatically initialize a new instance of a class, we can implement the initialize
method. The #initialize
message will be sent as soon as it is created.
We already have the code from our earlier snippet exercise; we just have to turn it into a method:
"protocol: #accessing" Jumble >> initialize | wordlistUrl words wordList | wordlistUrl := 'https://raw.githubusercontent.com/dwyl/english-words/master/words_alpha.txt'. words := (ZnUrl fromString: wordlistUrl) retrieveContents. wordList := Character cr asString , Character lf asString split: words. wordDict := Dictionary new. wordList do: [ :word | | key | key := word sorted. wordDict at: key ifPresent: [ :v | v addLast: word ] ifAbsentPut: [ { word } asOrderedCollection ] ]
Accept the changes and then you should be able to see the method we have created:
Jumble>>#initialize
Notice that the only changes to the original snippet are:
1. We added a method declaration in the first line (initialize
).
2. We declared the local variables wordlistUrl
etc. within or-bars (|...|
).
3. We declared key
as variable local to its block (|key|
).
Unjumbling
Now we just have to add the unjumble method:
"protocol: #accessing" Jumble >> unJumble: aString ^ wordDict at: aString sorted
Now we have our first working version:
Jumble new unJumble: 'gameses'
Next: test examples and code cleaning
This first version seems to work, but we have no tests, the Jumble fails with an exception if the word cannot be unjumbled, and the source file is hard-wired. To see how we can fix this, continue with: Introducing test examples and code cleaning
Links to Pages containing missing references - allowed failures to allow references to missing classes and methods in the page.