I want to implement a small class in Pharo so I have done this:
Object subclass: #Person
instanceVariableNames: 'name age'
classVariableNames: ''
category: 'Test'
and I want to simulate a constructor so I have made a method like the following:
newName:aName newAge:aAge
"comment stating purpose of message"
name:=aName.
age:=aAge.
^self.
but when I want to call it from the playground in Pharo like this:
objPerson:=Person newName:'Carl' newAge: 10.
it is not recognized by Pharo, what am I doing wrong?
Although in general I agree with Leandro's answer, it exposes accessors to the private properties.
Kent Beck in his Smalltalk Best Practice Patterns (which I highly recommend), proposes to use set
as a prefix for the instance-side constructor, e.g.:
"add to class side to 'instance creation' protocol"
Person>>class name: aName age: anAge
^ self new
setName: aName age: anAge;
yourself
"add to instance side to 'initialization' protocol"
Person>>setName: aName age: anAge
name := aName.
age := anAge.
This way you can control whether you will or will not expose the properties.
Or you could stick with your original naming and just add new
, which you forgot.
objPerson := Person new newName:'Carl' newAge: 10.
The expression Person newName: 'Carl' newAge: 10
is a message to the class object Person
. Therefore you have to implement it on the class side of Person
.
Your code needs to be tweaked like this
Person class >> newName: aName newAge: anAge
| person |
person := self new.
person name: aName.
person age: anAge.
^person
Note that in the code above self
refers to the class because the method is on the class side. But since person
is an instance of Person
, the messages name: aName
and age: anAge
have to be defined on the instance side.
Therefore, on the instance side, you need to add the two setters:
Person >> name: aString
name := aString
Person >> age: anInteger
age := anInteger
With these three methods you should be able to run your example.
Some additional comments on the coding style:
Firstly, I would have chosen a different selector for the "constructor" method (in Smalltalk we call these "instance creation" methods). For instance,
Person class >> named: aString age: anInteger
^self new name: aString; age: anInteger
Secondly, there is no need to use the temporary person
for the newly created instance as the expression self new
already refers to such an instance.
Finally, note the use of the cascade syntax in
^self new name: aString; age: anInteger
which means that the message age: anInteger
will be sent to the same receiver that name: aString
, which in this case happens to be the new instance returned by self new
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With