class initialization and class-side variables

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

class initialization and class-side variables

Jan Blizničenko
Hello

It seems I misunderstood some concept of classes in Pharo. My problem is following:
Let's say I have class named SomeClass (subclass of Object) and class named SubClass (subclass of SomeClass).

If I create instance variable on SomeClass and SomeClass>>#initialize which initializes the variable, it gets initialized also when SubClass instance is created.

Now I'm trying to do something similar for class-side variables, but with no success.
If I create class-side variable on SomeClass and SomeClass class>>#initialize which initializes the variable, it gets initialized only in SomeClass class, but not in SubClass class.

What I mean:

Object subclass: #SomeClass

 SomeClass class
         instanceVariableNames: 'Ok'

 SomeClass class>>#initialize
        super initialize.
        Ok := true

 SomeClass class>>#isOk
        ^ Ok

SomeClass subclass: #SubClass

calling "SomeClass isOk" returns true.
calling "SubClass isOk" returns nil.


now If I create method

 SubClass class>>#initialize
        super initialize.

SubClass initializes as I would expect from my experience with instance initialization, so "SubClass isOk" now returns true.


I will appreciate any help.

Jan
Reply | Threaded
Open this post in threaded view
|

Re: class initialization and class-side variables

Andrei Chis
Hi,

SomeClass and SubClass are two different objects.
Based on your setup, if you do not call any initialize method, initially calling both  "SomeClass isOk" and  "SubClass isOk" should return nil.

Running "SomeClass initialize" initializes only the SomeClass object. So now "SomeClass isOk"  returns true and "SubClass isOk" returns nil, as its another object that has not been initialized.
You get the same behaviour if you first call "SubClass initialize". Now "SomeClass isOk"  returns nil because you did not initialize the SomeClass object, but the SubClass.

Even if you add initialize in the SubClass class and call it first "SomeClass isOk" will still return false.
SomeClass and SubClass are just two different objects of types SomeClass class and  SubClass class. It's the same behaviour that you get when you create two instances of these classes. Just because you create an instance of the type SubClass and call super initialize,
it doesn't mean that another instance of SomeClass will be initialized.

Hope this makes sense/answers your question.

Cheers,
Andrei

On Wed, Apr 29, 2015 at 2:25 PM, Jan Blizničenko <[hidden email]> wrote:
Hello

It seems I misunderstood some concept of classes in Pharo. My problem is
following:
Let's say I have class named SomeClass (subclass of Object) and class named
SubClass (subclass of SomeClass).

If I create instance variable on SomeClass and SomeClass>>#initialize which
initializes the variable, it gets initialized also when SubClass instance is
created.

Now I'm trying to do something similar for class-side variables, but with no
success.
If I create class-side variable on SomeClass and SomeClass
class>>#initialize which initializes the variable, it gets initialized only
in SomeClass class, but not in SubClass class.

What I mean:

Object subclass: #SomeClass

 SomeClass class
         instanceVariableNames: 'Ok'

 SomeClass class>>#initialize
        super initialize.
        Ok := true

 SomeClass class>>#isOk
        ^ Ok

SomeClass subclass: #SubClass

calling "SomeClass isOk" returns true.
calling "SubClass isOk" returns nil.


now If I create method

 SubClass class>>#initialize
        super initialize.

SubClass initializes as I would expect from my experience with instance
initialization, so "SubClass isOk" now returns true.


I will appreciate any help.

Jan



--
View this message in context: http://forum.world.st/class-initialization-and-class-side-variables-tp4822869.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.


Reply | Threaded
Open this post in threaded view
|

Re: class initialization and class-side variables

Sean P. DeNigris
Administrator
In reply to this post by Jan Blizničenko
Jan Blizničenko wrote
Now I'm trying to do something similar for class-side variables, but with no success.
What you created is a class-side instance variable, which is private to just that class. What you want is a class variable, which is shared by all subclasses and instances. You declare it in the class definition with #classVariableNames:. There is a very nice explanation of these basic (but confusing!) concepts in the "Pharo By Example" book.
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: class initialization and class-side variables

Jan Blizničenko
Thank you both for reply. Unfortunately, it seems I didn't describe my goal well.

I want both (all) classes to have separate variables, not shared among subclasses, but still initialized on class side, not instance side. So I want those variables to be class-side variables, my problem is with their initialization. I have a tree of classes, top class (superclass of the rest) should have class-side variable initialized as empty collection, and almost all it's subclasses to have, by default, also an empty colletion. But there will be few classes in this tree, whose collections should contain something.

So to return to my previous example... I want SomeClass class-side variable "SomeCollection" to contain OrderedCollection()... SubClass along with many more subclasses to also contain OrderedCollection... but also to have a SpecificSubClass, whose class-side variable "SomeCollection" will contain OrderedCollection(something, somethingElse...).

Jan

Sean P. DeNigris wrote
What you created is a class-side instance variable, which is private to just that class. What you want is a class variable, which is shared by all subclasses and instances. You declare it in the class definition with #classVariableNames:. There is a very nice explanation of these basic (but confusing!) concepts in the "Pharo By Example" book.
Andrei Chis wrote
Hi,

SomeClass and SubClass are two different objects.
Based on your setup, if you do not call any initialize method, initially
calling both  "SomeClass isOk" and  "SubClass isOk" should return nil.

Running "SomeClass initialize" initializes only the SomeClass object. So
now "SomeClass isOk"  returns true and "SubClass isOk" returns nil, as its
another object that has not been initialized.
You get the same behaviour if you first call "SubClass initialize".
Now "SomeClass
isOk"  returns nil because you did not initialize the SomeClass object, but
the SubClass.

Even if you add initialize in the SubClass class and call it first "SomeClass
isOk" will still return false.
SomeClass and SubClass are just two different objects of types SomeClass
class and  SubClass class. It's the same behaviour that you get when you
create two instances of these classes. Just because you create an instance
of the type SubClass and call super initialize,
it doesn't mean that another instance of SomeClass will be initialized.

Hope this makes sense/answers your question.

Cheers,
Andrei
Reply | Threaded
Open this post in threaded view
|

Re: class initialization and class-side variables

Andrei Chis
Aha, now I understand your question.
From what I remember #initialize might only be send to classes if they contain an explicit initialize method, but I might remember wrongly.

Cheers,
Andrei

On Wed, Apr 29, 2015 at 3:08 PM, Jan Blizničenko <[hidden email]> wrote:
Thank you both for reply. Unfortunately, it seems I didn't describe my goal
well.

I want both (all) classes to have separate variables, not shared among
subclasses, but still initialized on class side, not instance side. So I
want those variables to be class-side variables, my problem is with their
initialization. I have a tree of classes, top class (superclass of the rest)
should have class-side variable initialized as empty collection, and almost
all it's subclasses to have, by default, also an empty colletion. But there
will be few classes in this tree, whose collections should contain
something.

So to return to my previous example... I want SomeClass class-side variable
"SomeCollection" to contain OrderedCollection()... SubClass along with many
more subclasses to also contain OrderedCollection... but also to have a
SpecificSubClass, whose class-side variable "SomeCollection" will contain
OrderedCollection(something, somethingElse...).

Jan


Sean P. DeNigris wrote
> What you created is a class-side instance variable, which is private to
> just that class. What you want is a class variable, which is shared by all
> subclasses and instances. You declare it in the class definition with
> #classVariableNames:. There is a very nice explanation of these basic (but
> confusing!) concepts in the "Pharo By Example" book.


Andrei Chis wrote
> Hi,
>
> SomeClass and SubClass are two different objects.
> Based on your setup, if you do not call any initialize method, initially
> calling both  "SomeClass isOk" and  "SubClass isOk" should return nil.
>
> Running "SomeClass initialize" initializes only the SomeClass object. So
> now "SomeClass isOk"  returns true and "SubClass isOk" returns nil, as its
> another object that has not been initialized.
> You get the same behaviour if you first call "SubClass initialize".
> Now "SomeClass
> isOk"  returns nil because you did not initialize the SomeClass object,
> but
> the SubClass.
>
> Even if you add initialize in the SubClass class and call it first
> "SomeClass
> isOk" will still return false.
> SomeClass and SubClass are just two different objects of types SomeClass
> class and  SubClass class. It's the same behaviour that you get when you
> create two instances of these classes. Just because you create an instance
> of the type SubClass and call super initialize,
> it doesn't mean that another instance of SomeClass will be initialized.
>
> Hope this makes sense/answers your question.
>
> Cheers,
> Andrei





--
View this message in context: http://forum.world.st/class-initialization-and-class-side-variables-tp4822869p4822886.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.


Reply | Threaded
Open this post in threaded view
|

Re: class initialization and class-side variables

Ben Coman
In reply to this post by Jan Blizničenko
Each class needs its *own* initialize method.  You can observe this behaviour as follows...

1. Create a new package MyPlay holding the following...

    Object subclass: #SomeClass

    SomeClass class>>#initialize
            self inform: 'Initializing... ' , self name.

    #SomeClass object: #SubClass "Notice that there was no inform message"

2. Export package to local disk using Monticello.

3. Delete MyPlay package.

4. Via Monticello load MyPlay package. 
     Observe that you only get an inform message for SomeClass, and not SubClass.


I wanted to understand this behaviour more, so I modified...

    SomeClass class>>#initialize
            self haltOnce.
            self inform: 'Initializing... ' , self name.

...then enabled haltOnce and repeated steps 2, 3, 4 -- which broke out from MCMethodDefinition>>postloadOver:
which shows #initialize is only called on classes where #initialize is defined.


So it seems that creating a new class does not call #initialize at all, let alone an inherited one.  It is a Monticello behaviour.

cheers -ben
                    

On Wed, Apr 29, 2015 at 8:25 PM, Jan Blizničenko <[hidden email]> wrote:
Hello

It seems I misunderstood some concept of classes in Pharo. My problem is
following:
Let's say I have class named SomeClass (subclass of Object) and class named
SubClass (subclass of SomeClass).

If I create instance variable on SomeClass and SomeClass>>#initialize which
initializes the variable, it gets initialized also when SubClass instance is
created.

Now I'm trying to do something similar for class-side variables, but with no
success.
If I create class-side variable on SomeClass and SomeClass
class>>#initialize which initializes the variable, it gets initialized only
in SomeClass class, but not in SubClass class.

What I mean:

Object subclass: #SomeClass

 SomeClass class
         instanceVariableNames: 'Ok'

 SomeClass class>>#initialize
        super initialize.
        Ok := true

 SomeClass class>>#isOk
        ^ Ok

SomeClass subclass: #SubClass

calling "SomeClass isOk" returns true.
calling "SubClass isOk" returns nil.


now If I create method

 SubClass class>>#initialize
        super initialize.

SubClass initializes as I would expect from my experience with instance
initialization, so "SubClass isOk" now returns true.


I will appreciate any help.

Jan



--
View this message in context: http://forum.world.st/class-initialization-and-class-side-variables-tp4822869.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.


Reply | Threaded
Open this post in threaded view
|

Re: class initialization and class-side variables

Jan Blizničenko
In reply to this post by Jan Blizničenko
Replying to myself...

Here is example package with tests of behavior I expect: http://www.mediafire.com/download/bjmt7p20ndcgddf/Something-bliznjan.6.mcz

Only way to aquire it seems to create initialize method in every subclass class, and write just "super initialize" there, but for about 30 subclasses (and many more in the future), it does not seem like fine solution.

Jan

Jan Blizničenko wrote
Thank you both for reply. Unfortunately, it seems I didn't describe my goal well.

I want both (all) classes to have separate variables, not shared among subclasses, but still initialized on class side, not instance side. So I want those variables to be class-side variables, my problem is with their initialization. I have a tree of classes, top class (superclass of the rest) should have class-side variable initialized as empty collection, and almost all it's subclasses to have, by default, also an empty colletion. But there will be few classes in this tree, whose collections should contain something.

So to return to my previous example... I want SomeClass class-side variable "SomeCollection" to contain OrderedCollection()... SubClass along with many more subclasses to also contain OrderedCollection... but also to have a SpecificSubClass, whose class-side variable "SomeCollection" will contain OrderedCollection(something, somethingElse...).

Jan

Sean P. DeNigris wrote
What you created is a class-side instance variable, which is private to just that class. What you want is a class variable, which is shared by all subclasses and instances. You declare it in the class definition with #classVariableNames:. There is a very nice explanation of these basic (but confusing!) concepts in the "Pharo By Example" book.
Andrei Chis wrote
Hi,

SomeClass and SubClass are two different objects.
Based on your setup, if you do not call any initialize method, initially
calling both  "SomeClass isOk" and  "SubClass isOk" should return nil.

Running "SomeClass initialize" initializes only the SomeClass object. So
now "SomeClass isOk"  returns true and "SubClass isOk" returns nil, as its
another object that has not been initialized.
You get the same behaviour if you first call "SubClass initialize".
Now "SomeClass
isOk"  returns nil because you did not initialize the SomeClass object, but
the SubClass.

Even if you add initialize in the SubClass class and call it first "SomeClass
isOk" will still return false.
SomeClass and SubClass are just two different objects of types SomeClass
class and  SubClass class. It's the same behaviour that you get when you
create two instances of these classes. Just because you create an instance
of the type SubClass and call super initialize,
it doesn't mean that another instance of SomeClass will be initialized.

Hope this makes sense/answers your question.

Cheers,
Andrei
Reply | Threaded
Open this post in threaded view
|

Re: class initialization and class-side variables

Sean P. DeNigris
Administrator
Jan Blizničenko wrote
Only way to aquire it seems to create initialize method in every subclass class
Maybe initialize all subclasses from the parent? But you'd have to reinitialize if you added more subclasses later...
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: class initialization and class-side variables

Jan Blizničenko
In reply to this post by Ben Coman
Thank you for sharing your experience with it. So, when I see all this, I think depending on initialize method on class side seems like a pretty bad idea. So I decided to leave this way of thoughts and I came up with lazy initialization. With lazy initialization it seems to work just fine and my problem is probably solved.

mcz if you want: http://www.mediafire.com/download/c4jwmkz58mb4e9t/Something-bliznjan.7.mcz

Thank you all for your help.

Jan

Ben Coman wrote
Each class needs its *own* initialize method.  You can observe this
behaviour as follows...

1. Create a new package MyPlay holding the following...

    Object subclass: #SomeClass

    SomeClass class>>#initialize
            self inform: 'Initializing... ' , self name.

    #SomeClass object: #SubClass "Notice that there was no inform message"

2. Export package to local disk using Monticello.

3. Delete MyPlay package.

4. Via Monticello load MyPlay package.
     Observe that you only get an inform message for SomeClass, and not
SubClass.


I wanted to understand this behaviour more, so I modified...

    SomeClass class>>#initialize
            self haltOnce.
            self inform: 'Initializing... ' , self name.

...then enabled haltOnce and repeated steps 2, 3, 4 -- which broke out from
MCMethodDefinition>>postloadOver:
which shows #initialize is only called on classes where #initialize is
defined.


So it seems that creating a new class does not call #initialize at all, let
alone an inherited one.  It is a Monticello behaviour.

cheers -ben
Reply | Threaded
Open this post in threaded view
|

Re: class initialization and class-side variables

Thierry Goubier
In reply to this post by Ben Coman
Le 29/04/2015 16:01, Ben Coman a écrit :
>
>
> So it seems that creating a new class does not call #initialize at all,
> let alone an inherited one.  It is a Monticello behaviour.

I'm nearly certain all other ways of loading smalltalk code in the image
behave like that; MC only reproduces an older convention.

Thierry

Reply | Threaded
Open this post in threaded view
|

Re: class initialization and class-side variables

Ben Coman

On Thu, Apr 30, 2015 at 12:51 AM, Thierry Goubier <[hidden email]> wrote:
Le 29/04/2015 16:01, Ben Coman a écrit :


So it seems that creating a new class does not call #initialize at all,
let alone an inherited one.  It is a Monticello behaviour.

I'm nearly certain all other ways of loading smalltalk code in the image behave like that; MC only reproduces an older convention.
 
Thanks Thierry.  Then what I meant was that calling the class-side #initialize seems not part of the class creation code.  I infer that those other ways of loading code must also themselves implement the behaviour the call #initialize after the class is loaded.  
cheers -ben