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 |
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 |
Administrator
|
In reply to this post by Jan Blizničenko
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 |
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
|
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 |
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 |
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
|
Administrator
|
Maybe initialize all subclasses from the parent? But you'd have to reinitialize if you added more subclasses later...
Cheers,
Sean |
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
|
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 |
On Thu, Apr 30, 2015 at 12:51 AM, Thierry Goubier <[hidden email]> wrote: Le 29/04/2015 16:01, Ben Coman a écrit : 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 |
Free forum by Nabble | Edit this page |