What is the difference between classVariableNames: '' and instanceVariableNames: '' when setting up a Singleton in Pharo Smalltalk? - smalltalk

One is located on the instance side:
Object subclass: #MyClass
instanceVariableNames: ''
classVariableNames: ''
category: 'MyApp'
The other accessible on the class side:
MyClass class
instanceVariableNames: ''

When you create a new class (For example a Pen) you create a Class that is an instance of metaclass (this will be Pen class) and you will be able to get Pen instances that are instance of Pen class.
You can have a lot of Pen but you will have only one Pen class.
An instance variable is a variable of one instance. Each instance has it's own variable. Each Pen can have it's own color.
A class variable is a variable of a Class object (Pen class). As you have only one instance of Pen class, this variable will have only one value. If your pen has a class variable #DefaultColor, myPenInstance class defaultColor will return the same for all the Pen instances.
And last, an instance variable of the class side works as an instance variable of the instance side but for a class.
The difference between a class variable and an instance variable in the class side is that the class variable is unique for the class and it's subclasses while an instance variable in the class side will be specific for each of it's subclasses.
If you have a UniqueInstance class variable that stores a Singleton with an accessor in you Pen, Pen uniqueInstance and PenSubclass uniqueInstance will return the unique pen instance.
If you do the same with an instance variable in the class side, Pen uniqueInstance will return the Pen unique instance and PenSubclass uniqueInstance will return the PenSubclass unique instance.

Here goes, I found bits of information here and there.
Managed to find a good explanation here, pasted in a few lines for reference purposes. People should read the entire column.
http://esug.org/data/Articles/Columns/EwingPapers/cvars&cinst_vars.pdf
Classes that use class variables can be made more reusable with a few
coding conventions. These coding conventions make it easier to create
subclasses. Sometimes developers use class variables inappropriately.
Inappropriate use of class variables results in classes that are
difficult to subclass. Often, the better implementation choice for a
particular problem is a class instance variable instead of a class
variable.
What are class variables? Classes can have
• class
variables, and
• class instances variables.
Class variables are
referenced from instance and class methods by referring to the name of
the class variable. Any method, either a class method or an instance
method can reference a class variable.

Related

Where are class variables defined in Smalltalk?

I was wondering, if I define a new class variable, for example for the class MyClass, is the definition going to be in MyClass or in MyClass class? Does MyClass class even know about the new class variable?
Yes, class variables are shared with the class and the metaclass. They are also shared with all subclasses (and their metaclasses). A class variable is usually Capitalized, to convey better the idea of being shared in a scope broader than the class. You define class variables in the class (not the metaclass).
Class variables should not be confused with class instance variables, which are instance variables defined at the metaclass level, i.e., instance variables of the class object. This notion is somewhat obscure despite its simplicity (or because of it): instance variables are always defined in the class to define the shape (slots) of its instances. Thus, if we apply this definition to the metaclass, which is the class of the class, an instance variable defined here defines the shape of its instances, of which there is (usually) only one, the class.
Going back to class variables, you define them in the class (inst side) and initialize them in the metaclass (i.e., class side). Remember that these are (partial) globals in the sense that will be shared among instances, subinstances, subclasses and metaclasses and so they must be handled with the usual care we treat globals.
One more clarification
When we say that instance variables are shared among instances and subinstances, we mean their names (and positions in memory of the object slots); we don't mean their values (contents of said slots). Thus, two instances of the class C will share the name, say color, if the class defines the ivar color, but their values at each of the instances will be independent. In other words, what it is shared is the name, not the value.
With class variables what is shared is both the name and the value. It is actually the Association object, for example Theme -> aTheme, what's shared. In consequence, any modification to the value of a class variable affects all its references. This is not the case with class instance variables because they are nothing but instance variables, except that they shape the class and its subclasses, rather than regular instances and subinstances.
For more information on Smalltalk variables see https://stackoverflow.com/a/42460583/4081336
Just as a complement to Leandro's answer, here is the main Squeak implementation specific method that explains the sharing of class variables between instance side (class) and class side (metaclass):
Metaclass>>classPool
"Answer the dictionary of class variables."
^thisClass classPool
where thisClassis the unique instance of the Metaclass, that is the class itself...
There are high chances though to find similar implementation in most Smalltalk dialects.
The compiler will first try to resolve the variable as a method/block temporary (including methd/block parameters), then instance variables, then shared variables.
The classPool method is sent by the compiler in this last phase.
A Leandro did explain, the compiler either resolve the binding just as an offset that will be directly transcripted in the bytecode in case of instance variable slot or method temporary variable, or as a kind of Association for the shared variable case, this association being generally added to the CompiledMethod literals and effectively shared among all methods dealing with this variable (all methods points to the same Assocation object which is effectively shared).
The compiler part is much more dialect specific, in Squeak, it's this method which is used for resolving the binding of shared variables:
class>>bindingOf: varName environment: anEnvironment
"Answer the binding of some variable resolved in the scope of the receiver"
| aSymbol binding |
aSymbol := varName asSymbol.
"First look in local classVar dictionary."
binding := self classPool bindingOf: aSymbol.
binding ifNotNil:[^binding].
"Next look in local shared pools."
self sharedPools do:[:pool |
binding := pool bindingOf: aSymbol.
binding ifNotNil:[^binding].
].
"Next look into superclass pools"
superclass ifNotNil: [^ superclass bindingOf: aSymbol environment: anEnvironment].
"No more superclass... Last look in declared environment."
^anEnvironment bindingOf: aSymbol
This is to remind you that one of the most interesting part of Smalltalk is that you can dig into the implementation from within the IDE, Smalltalk is essentially written in Smalltalk!

Overriding subclass method in squeak

I need to make a new subclass method to a new classs that i created who got 2 class instance varribles : isInterface and behavesLike.
i need to make a subclass method that gets this parameters as well and creates a new sub class with thos parameters.
i just cant get what am i doing wrong here .
this is my code :
subclass: aSubclassName isInterface: isInterface behavesLike:
aCollection instanceVariableNames: instVarNames classVariableNames:
classVarNames poolDictionaries: poolDictionaries category:aCategoryName
|m|
m:=(super subclass: aSubclassName
instanceVariableNames: instVarNames
classVariableNames:classVarNames
poolDictionaries: poolDictionaries
category: aCategoryName).
(m class) instVarNamed:'behavesLike' put:aCollection;instVarNamed:'isInterface' put:isInterface
^(m class).
i just keep getting those errors :
You are mixing class and instance level, a very frequent issue.
Classes are artifacts that create instances. And instVars are, precisely, in the instances.
In your case,
(m class) instVarNamed:'behavesLike' put:aCollection
attempts to set the instance var of a class, because m class is a class. If you want an instance, you should talk to m class new, but even worse, because m itself is a class, so m class is a metaclass. To understand all this confusion, you should read the chapters about Metaclasses in the Blue Book.
But to fix your code, m new instead of m class should work

How to initialise a class variable?

I know that for an instance variable all I have to do is put it inside the initialise method in the instance side and assign it a default value. But how I do this for class variable ? I tried to create an initialise method at class side but it did not give my variable a default value so I had to do this in one of my methods
pythonString ifNil:[pythonString := '']
But I don't like this approach.
I also found this for squeak , http://forum.world.st/Howto-initialize-class-variables-td1667813.html again I don't like this approach either. Is there a proper way of doing this. In Python it was fairly simple case of assignment why is it so cryptic for Pharo ?
First of all I hope that you are talking about instance variable of a class object (not a thing that you define on instance side as "class variable").
initialize is working, but it's being run upon instance creation. And instance (a class object) exists already when you define initialize method.
So when you define your class for the first time, you should run it by yourself e.g. YourClass initialize, bun later each time you load your class into system it should be initialised.

Class Method not working in objective c

In my code I have a class called 'ProfileShareViewController', In which I have imported another class I have created called 'OwnProfileData', And I have also created an Instance of that class (class = OwnProfileData) as a property Of 'ProfileShareViewController' and synthesized it (instance called 'OwnProfile').
In another class I have called 'EditProfileViewController', I have imported the 'ProfileShareViewController', and now I am trying to change a property of the OwnProfile object from the ProfileShareViewController within the EditProfileViewController class.
For some reason that doesn't work. I have Tried typing:
[[ProfileShareViewController ownProfile] setName:#"Ido"];
(The property I am trying to set is Name, and as it is synthesized in OwnProfileData, I am using 'setName').
This doesn't work and I get the warning: "No known class method for selector 'ownMethod'.
Any Idea as for why that might happen and how I can fix this?
Thanks for your comments! Any support is highly appreciated!
You need an instance of ProfileShareViewController, because ownProfile is an instance property, not an class method. Read about the differences between classes and instances.
Or did I misunderstood smth?

What is an instance variable?

I'm a beginner. I want to know what an instance variable is.
In object-oriented programming with classes, an instance variable is a variable defined in a class (i.e. a member variable), for which each object of the class has a separate copy. They live in memory for the life of the class.
An instance variable is the opposite of class variable, and it is a special type of instance member. An example of an instance variable is "private double length"
Technically speaking, instance variables are objects stored in individual states in "non-static fields", that is, fields declared without the static keyword. Non-static fields are also known as instance variables because their values are unique to each instance of a class (to each object, in other words); the currentSpeed of one bicycle is independent from the currentSpeed of another.
References:
http://en.wikipedia.org/wiki/Instance_variable
You probably mean "instance" variable. It is a variable that is associated with instances of a class. For each instance of a class you create, that variable is also created.