Search code examples
objectsmalltalkgnu-smalltalk

Why this class/instance variable is not being intialized?


I am trying to use gnu-smalltalk. In following code of a simple class with a variable, I find it is not getting initialized to the given value:

Object subclass: Myclass[
    |mainval|
    mainval := 555.
    getmainval [^mainval]
]

gc := Myclass new.
gc getmainval printNl.

The object gets created without any error. But, the output is:

nil

while I had expected it to be 555.

If I add a method to assign a value to it and call it after creating an instance of the class, it works.

Where is the problem and how can it be corrected? Thanks.


Solution

  • I think you were close but you tried a shortcut which does not work due to the fact that you are expecting that setting value to an instance variable within class definition (outside a method and local validity) will return value. In reality you want to use an instance variable within a method e.g. init to express the inner state of an object.

    As I have noted in some previous answers, I'm not a GNU Smalltalk expert. I'm using Smalltalk/X-jv branch for programming.

    I have taken the liberty to rewrite your code to more GNU Smalltalk like code:

    Object subclass: MyClass [
        | mainVal |
        <comment:
            'testing main value'>
        MyClass class >> new [
            <category: 'instance creation'>
            | myClass |
            myClass := super new.
            myClass init.
            ^ myClass
        ]
        init [
            <category: 'initialization'>
            mainVal := 555.
        ]
        mainVal [
            ^ mainVal
        ]
    ]
    

    The explanation:

    I'm defining the mainVal instance variable. Then I'm redefining a class method new which is not needed but for illustration purposes I'm doing so. (The new message is inherited from Object class)

    What I'm doing in the class method new. I'm sending the new message to the superclass which creates instance of anObject, then initializing the myClass with init and then returing it.

    Afterwards you can see the init class which initialize your instance variable to your wished value of 555.

    Then you have a getter (in Smalltalk it is usual to have it without the get prefix, but that is "only" matter of style) the mainVal.

    Then your code to call the object and get value.

    gc := MyClass new.
    gc mainVal
    

    The minimal example without the new message redefinition:

    Object subclass: MyClass [
        | mainVal |
        <comment:
            'testing main value'>
        init [
            <category: 'initialization'>
            mainVal := 555.
        ]
        mainVal [
            ^ mainVal
        ]
    ]
    

    What you must not forget that in Smalltalk there is usually no default calling of a constructor so you have to send the init message manually (the other option is to redefine new message like I did above).

    Then using it would look like this:

    gc := MyClass new.
    a MyClass
    st> gc init
    a MyClass
    st> gc mainVal
    555