What's the trick / catch ... if there is one for invoking a class method from a workspace?
I created a Class "MikeTest".
- Added an instance method : "imethod"
MikeTest >> imethod ^ 'I am an instance method'
- Added a Class method
MikeTest class>>cmethod ^ 'I am a class method'
---- Then in a workspace :
t := MikeTest new. t imethod (alt-p) -->> 'I am an instance method' (As expected)
t cmethod (alt-p) gives 'MessageNotUnderstood'
http://mstram.freepgs.com/img/message_not_understood_when_evaluating_class_m...
The debug trace has 'UndefinedObject>>Doit' ... which seems strange to me ... does that mean the workspace doesn't understand how to send a class method ???
Puzzled (again).
Mike
El 5/26/07 9:50 AM, "mstram" mstramba@sympatico.ca escribió:
What's the trick / catch ... if there is one for invoking a class method from a workspace?
I created a Class "MikeTest".
- Added an instance method : "imethod"
MikeTest >> imethod ^ 'I am an instance method'
- Added a Class method
MikeTest class>>cmethod ^ 'I am a class method'
Then in a workspace :
t := MikeTest new. t imethod (alt-p) -->> 'I am an instance method' (As expected)
t cmethod (alt-p) gives 'MessageNotUnderstood'
http://mstram.freepgs.com/img/message_not_understood_when_evaluating_class_m... hod.jpg
The debug trace has 'UndefinedObject>>Doit' ... which seems strange to me ... does that mean the workspace doesn't understand how to send a class method ???
Puzzled (again).
Mike
do MikeTest cmethod.
Edgar
Edgar J. De Cleene wrote:
do MikeTest cmethod.
Ok thx, have it working now.
Though I ran into an error when I tried to use :
do MikeTest cmethod.
and changed it to just
MikeTest cmethod.
:)
also :
avar := MikeTest cmethod
also works, as I'm sure you know .. but took me a minute to think of ;)
Mike
Hi mstram,
on Sat, 26 May 2007 14:50:34 +0200, you wrote:
What's the trick / catch ... if there is one for invoking a class method from a workspace?
I created a Class "MikeTest".
- Added an instance method : "imethod"
MikeTest >> imethod ^ 'I am an instance method'
- Added a Class method
MikeTest class>>cmethod ^ 'I am a class method'
Then in a workspace :
t := MikeTest new. t imethod (alt-p) -->> 'I am an instance method' (As expected)
t cmethod (alt-p) gives 'MessageNotUnderstood'
http://mstram.freepgs.com/img/message_not_understood_when_evaluating_class_m...
The debug trace has 'UndefinedObject>>Doit' ... which seems strange to me ... does that mean the workspace doesn't understand how to send a class method ???
The line with UndefinedObject>>DoIt is how the compiler invokes the expression when you do (alt-p). When you select that line, you can see your expression decompiled. So, no problem.
The other question was answered by Edgar.
/Klaus
Puzzled (again).
Mike
On May 26, 2007, at 14:50 , mstram wrote:
What's the trick / catch ... if there is one for invoking a class method from a workspace?
"Class methods" in Smalltalk are regular methods, because classes are regular objects. Unfortunately the browser gives the impression that there are two kinds of methods ...
MyClass new
simply sends #new to the object MyClass. This is how you invoke a "class method".
Remember, anything in Smalltalk is an object. Even classes. There is not even a "syntax" to define a class or a method (just like there is no syntax for control structures). Everything is accomplished by sending messages.
- Bert -
Well obviously I need to a lot more reading and experimenting with this, even if "class" methods are "regular" methods, there is something different with them as far as :
1) the syntax to access them ("fire" .. "call" .. "invoke" ??? what is the traditional term ? )
2) At least one difference I've found is that I when tried to create a "class" method that accessed an instance variable, Squeak warned that the variable didn't exist and asked if I wante to create it (is this a bug?) ... even though it was "declared" in the class definition.
I tried modifying my MikeTest to :
Object subclass: #MikeTest instanceVariableNames: 'ivar1' classVariableNames: 'Cvar1' poolDictionaries: '' category: 'Mike1'
and adding :
A) -----------"instance method " -------------------------------
imet: ivar icmet: cvar ivar1 := ivar. Cvar1 := cvar. ^ 'I am an instance method' ---------------------------------------------
iget |temp| temp := Dictionary new. temp at: 'ivar1' put: ivar1. temp at: 'cvar1' put: Cvar1. ^ temp.
and
B) --------------"class method " -------------------------------- cmet: ivar ccmet: cvar ivar1 := ivar. Cvar1 := cvar.
Cvar1 := cvar. ^ 'I am a Class Method' -------------------------------------------------------------- cget |temp| temp := Dictionary new. temp at: 'cvar1' put: Cvar1. temp at: 'ivar1' put: ivar1. ^ temp. =================================
(I realize 'iget' and 'cget' are the same thing, I just wanted to see if there is any difference when running them.)
But Squeak says that 'ivar1' is undeclared and asks if I want to declare it. It accepts it being declared as an instance variable (even though it already was according to the class definition ... (is this a bug?).
I can set / retrieve the variables with either the "class" or "instance" methods, so I'm not sure why Classes have been setup in Squeak using both types of methods.
t1 := MikeTest new.
result := MikeTest cmet: 'Class method setting inst var ivar1-> inst44' ccmet: 'Class method setting class var Cvar1 -> Class01'
Bert Freudenberg-2 wrote:
On May 26, 2007, at 14:50 , mstram wrote:
What's the trick / catch ... if there is one for invoking a class method from a workspace?
"Class methods" in Smalltalk are regular methods, because classes are regular objects. Unfortunately the browser gives the impression that there are two kinds of methods ...
MyClass new
simply sends #new to the object MyClass. This is how you invoke a "class method".
Remember, anything in Smalltalk is an object. Even classes. There is not even a "syntax" to define a class or a method (just like there is no syntax for control structures). Everything is accomplished by sending messages.
- Bert -
On May 26, 2007, at 18:32 , mstram wrote:
Well obviously I need to a lot more reading and experimenting with this, even if "class" methods are "regular" methods, there is something different with them as far as :
- the syntax to access them ("fire" .. "call" .. "invoke" ???
what is the traditional term ? )
There is no special syntax. The only difference is the receiver. Either you send a message to an instance of a class or or the class itself (which, as mentioned before, is a regular object).
- At least one difference I've found is that I when tried to create a
"class" method that accessed an instance variable,
Instance variables are private, they can only be accessed by the object itself. So from the class object you cannot access instance variables of one of its instances.
Squeak warned that the variable didn't exist and asked if I wante to create it (is this a bug?) ... even though it was "declared" in the class definition. [...] But Squeak says that 'ivar1' is undeclared and asks if I want to declare it. It accepts it being declared as an instance variable (even though it already was according to the class definition ... (is this a bug?).
No, what you did there is you defined 'ivar1' as an instance variable of the class object itself, not for instances of your class. It will be listed in the browser when you switch to the class side definition. This feature is very rarely used.
- Bert -
On Saturday 26 May 2007 10:02 pm, mstram wrote:
- At least one difference I've found is that I when tried to create a
"class" method that accessed an instance variable, Squeak warned that the variable didn't exist and asked if I wante to create it (is this a bug?) ... even though it was "declared" in the class definition.
Mike,
Think of instantiation and declaration as being like icecream and its récipé. You can make many cups of icecreams from the same récipé. The instance variable (cherry) declared in the class definition (récipé) will be created only when a object of this class is created (icecream pie). You cannot assign to an instance variable in a class method anymore than you can eat cherries from a récipé :-). You 'browse' a récipé and 'inspect' or 'explore' the icecream :-).
This analogy doesn't apply exactly to Squeak. Since classes are also objects that are created when you 'accept' the definition (except that its variables are created from classVariableNames), so you can use them in class methods immediately. Like Bert explained in an earlier mail, use of classVariables is very rare.
Enjoy .. Subbu
On May 27, 2007, at 17:14 , subbukk wrote:
Since classes are also objects that are created when you 'accept' the definition (except that its variables are created from classVariableNames), so you can use them in class methods immediately.
Not quite. Those variables are "class variables", which are global variables (global to the class and subclasses and all their instances). Their names start with a capital letter like every global variable in Smalltalk.
Like Bert explained in an earlier mail, use of classVariables is very rare.
There is a difference between "class variables" (which are like "static" variables in other systems, so they get their fare share of use) and "class instance variables" (very rarely used indeed). You see "class instance variables" only when you switch the browser to the class side. "Class instance variables" have a different value in each subclass and are private to the class-side. Hence they are not global and have lower-case names.
- Bert -
On Sunday 27 May 2007 9:44 pm, Bert Freudenberg wrote:
There is a difference between "class variables" (which are like "static" variables in other systems, so they get their fare share of use) and "class instance variables" (very rarely used indeed). You see "class instance variables" only when you switch the browser to the class side. "Class instance variables" have a different value in each subclass and are private to the class-side. Hence they are not global and have lower-case names.
Thank you for explaining this in detail. I missed the fact that instance variables listed by browser on the class side are different from those on the instance. If I understood this correctly: (class instance) variables - variables global to all objects instantiated from a class
class (instance variable) - instance variable of the class (treated as an object and therefore visible only to its methods and methods in its subclasses).
BTW, I used the code below to inspect classes with explicit CIVs: (Smalltalk values select: [ :c | (c isKindOf: Class) and: [c class allInstVarNames size > 13 ] ]) collect: [ :d | { d . d class allInstVarNames size} ]
but this gave me classes that inherit them too. Is there a way to tease out classes that *define* CIVs?
Regards .. Subbu
On Jun 4, 2007, at 19:40 , subbukk wrote:
On Sunday 27 May 2007 9:44 pm, Bert Freudenberg wrote:
There is a difference between "class variables" (which are like "static" variables in other systems, so they get their fare share of use) and "class instance variables" (very rarely used indeed). You see "class instance variables" only when you switch the browser to the class side. "Class instance variables" have a different value in each subclass and are private to the class-side. Hence they are not global and have lower-case names.
Thank you for explaining this in detail. I missed the fact that instance variables listed by browser on the class side are different from those on the instance. If I understood this correctly: (class instance) variables - variables global to all objects instantiated from a class
This sounds more like "class variables".
class (instance variable) - instance variable of the class (treated as an object and therefore visible only to its methods and methods in its subclasses).
I don't think that is correct - what do you mean by "treated as an object"? I may be repeating myself, but *everything* is "treated as an object", because it is.
There really is only a difference between local and global variables. Local vars are lowercase by convention and local to an object instance ("instance variables") or a method activation ("temporary variables", "arguments"). There are special byte codes to access them. Global variables are uppercase by convention and are actually Associations (key->value pairs) held in dictionaries known to the compiler, and the Association gets stored as literal in a CompiledMethod. Their "globalness" differs in what dictionary ("variable pool") they live in - the one called "Smalltalk", or the "classPool" inst var of classes (these are "class variables"), or in shared pools (pools that are listed in the "sharedPool" class inst var, or whatever other dictionaries where given to the compiler (like "References" for etoys scripts).
BTW, I used the code below to inspect classes with explicit CIVs: (Smalltalk values select: [ :c | (c isKindOf: Class) and: [c class allInstVarNames size > 13 ] ]) collect: [ :d | { d . d class allInstVarNames size} ]
but this gave me classes that inherit them too. Is there a way to tease out classes that *define* CIVs?
Smalltalk allClasses select: [:ea | ea class instVarNames size > 0]
So one of them is Beeper. Just do a "Beeper inspect" to see its class inst vars, or to see which superclass defines what, do:
Beeper class withAllSuperclasses collect: [:ea | ea -> ea instVarNames]
an OrderedCollection( Beeper class->#('default') Object class->#() ProtoObject class->#() Class->#('subclasses' 'name' 'classPool' 'sharedPools' 'environment' 'category') ClassDescription->#('instanceVariables' 'organization') Behavior->#('superclass' 'methodDict' 'format') Object->#() ProtoObject->#() )
- Bert -
On Tuesday 05 June 2007 1:21 am, Bert Freudenberg wrote:
class (instance variable) - instance variable of the class (treated as an object and therefore visible only to its methods and methods in its subclasses).
I don't think that is correct - what do you mean by "treated as an object"? I may be repeating myself, but *everything* is "treated as an object", because it is.
In Smalltalk, classes are first order objects. I need to keep reminding myself about this :-) because in many imperative languages this is not true.
Smalltalk allClasses select: [:ea | ea class instVarNames size > 0]
Thanks for this hint. This is what I needed: Smalltalk allClasses select: [ :c | c class instVarNames size > 0 ] thenCollect: [ :c | c -> c class instVarNames ].
I had dropped the 'class' method and instVarNames didn't work. No wonder. 28 classes out of 2043 define their own instance variables. Rare indeed!
Thanks a lot .. Subbu
On Jun 5, 2007, at 7:55 , subbukk wrote:
On Tuesday 05 June 2007 1:21 am, Bert Freudenberg wrote:
class (instance variable) - instance variable of the class (treated as an object and therefore visible only to its methods and methods in its subclasses).
I don't think that is correct - what do you mean by "treated as an object"? I may be repeating myself, but *everything* is "treated as an object", because it is.
In Smalltalk, classes are first order objects. I need to keep reminding myself about this :-) because in many imperative languages this is not true.
Smalltalk allClasses select: [:ea | ea class instVarNames size > 0]
Thanks for this hint. This is what I needed: Smalltalk allClasses select: [ :c | c class instVarNames size > 0 ] thenCollect: [ :c | c -> c class instVarNames ].
I had dropped the 'class' method and instVarNames didn't work. No wonder. 28 classes out of 2043 define their own instance variables. Rare indeed!
And even of these few, some are in error and should really be class vars instead.
- Bert -
beginners@lists.squeakfoundation.org