Search code examples
smalltalk

smalltalk difference new & initialise


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


Solution

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