smalltalk difference new & initialise

63 Views Asked by At

I have the following three snippets of code (run in Pharo), where I would like to understand why and how the following does (not) work to understand new and initialise

a := Point initialize. this does not produce an error, but when inspecting it, the class Point does not initialise any x and y variables to nil (why?)

a := Point.
a x: 5 y:6.

This works, yields a vector 5@6. Why is there no need to invoke new when calling a point.

a := Point new.
a x:5 y:6.

This does not work, yields an error. Why? see above

2

There are 2 best solutions below

2
James Foster On BEST ANSWER

A key (but somewhat confusing) idea in Smalltalk is that there are methods associated with an instance and there are methods associated with the class. It is confusing because you need to keep track of whether you are sending a message to (or "calling") an instance method or a class method. (The Pharo system browser has a pair of radio buttons for "Inst. side" and "Class side".)

In your first example, Pharo initialize your are calling the class side initialize method (and since there is no implementation on the class side of Point, it executes the method found in the class side of Object). Importantly, for your purposes, the initialize method implicitly answers self, the receiver, which is the class Point.

In your second example you are storing a reference to the class Point in a variable a. Note that this is not a new object, but simply another reference to the existing (Point class) object. In the next line you send the message x:y: to the class Point. If you look at the class side implementation of x:y: you see that it calls basicNew which answers a new instance of Point and then it sends the message setX:setY: to that instance. If you look at the implementation of setX:setY: on the instance side of Point, you see that it sets the x and y values.

Your third example gives an error because the new message returns an instance of Point and there is not an x:y: message implemented on the instance side of Point.

Consider the following:

| pClass pInstance |
pClass := Point. "another reference to the class"
pInstance := pClass new. "calls a class-side method to create an instance"
pInstance setX: 5 setY: 6. "calls an instance-side method to set values"
pInstance

Or, more simply,

| pInstance |
pInstance := Point x: 5 y: 6. "a class-side method returns an initialized instance"

Note that this gets especially confusing when the same method name exists on both the class side and the instance side. This is not allowed in many OO languages since there is only one method namespace per class (and the class methods are designated as static). In Smalltalk, however, since classes are really first-class objects themselves they have their own method namespace. Once you get the hang of it, it really makes a lot of sense and is quite elegant.

0
Tony Giaccone On

Just to elaborate a bit on what's been said already.

a := Point initialize.
a class. 

If you do a print it on that last statement that you'll get -> Point class

b := Point x: 5 y: 3. 
b class

If you do a print it on that last statement that you'll get -> Point

The difference is that in the first case you're getting an instance of the Point class. That class is used to generate new instances of Point. In the second case you're getting an instance of Point. That is the thing you really wanted.

Finally if you browse the class Point, you'll find there is no message x:y: That message exists solely on the Instance side of Point the x and y values are supposed to be immutable once assigned to an instance.

This point is further emphasized by the fact that there is a message setX:setY but it's categorized as 'Private' which tells you again that you shouldn't use it.