Do classes like UndefinedObject behave like a singleton in Pharo - smalltalk

I am learning Pharo and I want to understand if classes/objects like nil which belongs to UndifnedObject class have only 1 instance and act like a singleton, or is a new instance made every time we have a nil.

The symbol nil refers to the single instance of UndefinedObject. You will find the same for true and false (sole instances of True and False respectively).

Related

In what circumstances do i need my own initializes to initialize object?

I know objective c has built in 'init' method to initialize object. But i want to know In what circumstances do i need my own initializes to initialize object?
I want to know what value is assigned to self when i invoke 'self = [super init]'
You only need your own initializer when you need your object to default to a state that is different than what the compiler will enforce. That is, all instance variables are initialized to 0 (for integer-like types) or 0.0 (for floating point types). That means all pointers are nil and all numbers are 0(.0). If you need to initialize anything to a different value (creating internal container objects, for example), you need your own initializer.
Similarly, if your class inherits from a class that implements its own initializer, you only need your own if you want your state to be different than the superclass's.

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.

Visualworks Cincom Smalltalk Class Variable Destruction

How can we initialize a class variable in Visualworks Smalltalk and destroy it after its use?
I want to know about ClassVariables. NOT ClassInstanceVariables.
I am implementing Singleton pattern and here is my code
MyClass class>> aClasMethod
aClassVariable isNil ifTrue:[
aClassVariable := 'I am a variable'.
]
^aClassVariable.
Once the variable is created, I am not able to destroy it.
i.e Next time I run my code, I see that the class variable is retaining its previous value.
How can I avoid this?
I tried this:
MyClass allInstances do: [:inst |
inst become: nil
].
But of no use.
The best way is simply to add a class method to set the class variable to nil and then call it whenever it's an appropriate time to clear it. I do this all the time with the Singleton pattern.
i think we usually use singleton pattern so that we only have one object. I don't know why do you want to store a string value in the class variable. Try to store a object so you will have only one copy of that specific object and store values in the instance variables. so that specific object has only some specific values. Then in future if u need to update the values stored in instance variable then make one more method updateValues and do everything in that.

Squeak Smalltalk: initialize don't work for class derived from Array?

I'm a bit of a novice when it comes to Squeak Smalltalk, so I'll probably done something wrong or made an erroneous assumption about how Squeak should work. Still, I'd like to know where I went wrong...
I tried to make class Blower derived from Array. Blower is basically an Array, but with an additional instance variable called index and some methods. I thought the initialize method would be automatically run when I created a new object, and that it would initialize both the array and the index variable, but this doesn't seem to happen. If I run initialize "manually" later though, it works as expected.
Array variableSubclass: #Blower
instanceVariableNames: 'index'
(...)
Blower >> initialize
super initialize.
1 to: self size do: [ :ix | self at: ix put: ix ].
self shuffle.
index := 1.
If I do the following in a workspace:
blower := Blower new: 10.
blower inspect.
Inspect-window shows (Not what I expected):
\#( nil nil nil nil nil nil nil nil nil nil )
index: nil
If I run initialize manually, Inspect-window is correct:
blower initialize.
\#( 6 4 1 10 2 8 3 ... )
index: nil
So why doesn't initialize run when I create the Blower and set it up correctly?
Is there anyway to automate this so it happens on creation? Ie. getting initialize to work?
Look at the method ArrayedCollection class >> new. It overrides new to call new: with 0 as a parameter. This replaces the default implementation of new in Behavior which calls initialize. If you really want to do this, implement new and new: as class methods in your class. In each case, call super then call initialize.
new
^super new initialize
new: sizeRequested
^(super new: sizeRequested) initialize
Having said all that, it's a really bad idea to subclass from Array. Ask yourself "Is it reasonable for me to use a Blower any place I currently use an Array?". If not, it's not a good subclass. Any time you subclass from a collections class you're almost always doing it wrong. What you want is a class called Blower which is a subclass of Object and contains two instance variables - one for the array and one for the index. Your class will now initialize normally. For any operations you want to send to the array, write a method in the Blower to delegate it to the instance variable.
What David Buck said is correct, but there is a few more things to add, specific to Squeak:
Some collections invoke #initialize: instead of #initialize at instance creation (see for example HashedCollection)
Some other could send both #initialize then #initialize: (see SharedQueue)
But Array class>>new: has a specific implementation that completely bypasses initialize (for the sake of speed, it is known that there is nothing required for initializing an Array)
As David said, it is generally a bad idea to subclass Array, and looking at Squeak, there are too many counter-examples already.

Subclass "is" class confuses me

I'm studying up on archiving data, and I realize the standard collection classes provide easy archival, however I want to archive an NSMutableArray. So I read that since NSMutableArray "is a" NSArray because it is a subclass, then this is fine.
But that idea stumps me, and I realize this is a basic concept of Objective-C so I want to make sure I get it right.
Suppose you have a class "automobile" with a subclass "jeep." Now based on the above, you can say this:
automobileInstance=jeepInstance;
...because a jeep is a subclass of automobile.
But this seems backwards to me. I would think you should instead say that a subclass instance can be equal to its superclass instance:
jeep = auto
Because after all a jeep "is a" automobile, but not all automobiles are jeeps.
So why then can you do this:
NSArray*newArray=nsmutableArrayInstance;
It's the same idea as saying:
automobile=jeep; in my example.
Your subclass might have added many new instance variables, for example, but if you set it equal to a superclass, those iVars are "lost" or at least the super class doesn't recognize them, so it isn't truly capturing the object, it would seem.
Going the other way, saying the sublass instance = superclass instance makes sense, since everything in the superclass is in the subclass; you just don't get values for the extra iVars that are in the subclass but not in the superclass, they might be set to default zero, but at least they exist.
Think of it this way: all jeeps are automobiles. Not all automobiles are jeeps. So you can say:
Automobile a = jeepInstance; // A jeep is always an automobile
But not:
Jeep j = autoInstance; // fails - autoInstance might be a Mazda, instead.
A superclass pointer can point to an object allocated from the subclass, since the class members of the superclass are always present in the subclass.
autoMobilePointer = jeepObject; // works
This isn't true the other way around, since the subclass has members that are not present in the superclass.
jeepPointer = autoMobileObject; // doesn't work
I think the problem here is that you're confusing assignment and equality, and maybe classes and objects, too. Remember that = means assignment, whereas == and -isEqual are tests for equality. If B is a subclass of A, then every B is an A, just as every Jeep is an automobile, and every human is a mammal.
But when you say:
automobile = jeep;
what you're doing is assigning the value of jeep to the variable automobile. You're not saying that every automobile in the world is a Jeep, you're saying that the specific variable automobile refers to a specific instance of Jeep. It's exactly as if I asked you:
What car do you drive?
In my head, I'm expecting you to reply with information about some car. You could say that the memory location in my head that I've reserved for your answer has type Automobile*, since it could refer to any car. You reply:
I drive that red Jeep parked near the tree.
It might help to choose more descriptive names for your variables. Use something specific, like:
Automobile *theCarThatAndrewxDrives = jeep;
This makes it obvious that we're talking about one specific car, not all cars.