I'm a new user (actually studying it in a course) in Smalltalk (Squeak). I have a method to check if one rectangle equals to a given rectangle which looks like this:
isEqual:givenRec
self a = givenRec a
ifTrue: [
self b = givenRec b
ifTrue: [
^true
].
^false
].
self b = givenRec a
ifTrue: [
self a = givenRec b
ifTrue: [
^true
].
^false
].
^false
my question is - is there a way to better write this? for it to be more compact?
also - why cant I refer to a
which is instanceVariableNames with self inside methods?
thanks for the help!
EDIT:
this is how the class is defined:
MyShape subclass: #MyTriangle
instanceVariableNames: 'a b c'
classVariableNames: ''
poolDictionaries: ''
category: 'Ex2'
MyShape
simply derives from Object
and has nothing.
You can make that more compact, yes.
First, besides #ifTrue:
there is also #ifFalse:
and #ifTrue:ifFalse:
, roughly having the effect of if-not--then and if--then--else.
But also, we already have a logical AND condition, so why not use that:
isEqual: givenRec
(self a = givenRec a and: [self b = givenRec b])
ifTrue: [^ true].
(self b = givenRec a and: [self a = givenRec b])
ifTrue: [^ true].
^false
With #ifTrue:ifFalse:
isEqual: givenRec
(self a = givenRec a and: [self b = givenRec b])
ifTrue: [^ true]
ifFalse: [^ (self b = givenRec a and: [self a = givenRec b])]
Also, we can do the return around the whole statement:
isEqual: givenRec
^ (self a = givenRec a and: [self b = givenRec b])
ifTrue: [true]
ifFalse: [self b = givenRec a and: [self a = givenRec b]]
But ifTrue: [true]
is a bit redundant, let's use #or:
isEqual: givenRec
^ (self a = givenRec a and: [self b = givenRec b]) or:
[self b = givenRec a and: [self a = givenRec b]]
Nice and sweet, we also see the logical structure pretty easily. (note that I diverge from common formatting styles to point out the similarities and differences in the two logical expressions).
We now have only one return ^
, no #ifTrue:…
For the instance variable question:
When you define some instance variables in the class like you did, you can use them literally in your code to access them:
Object subclass: #Contoso
instanceVariableNames: 'things'
classVariableNames: ''
poolDictionaries: ''
category: 'Examples'
isThingPlusThreeSameAs: anObject
^ thing + 3 = anObject
But typically, it is better to refer to instance variables via getters and setters, commonly called accessors. You have to write them manually or use the 'create inst var accessor' menu item of the second context menu (via “more…”) of a class in the browser:
This will generate accessor methods of the form
thing
^ thing
thing: anObject
thing := anObject
and you can use them in other methods like this
isThingPlusThreeSameAs: anObject
^ self thing + 3 = anObject