I need to know if it is possible to pass a Class as a parameter to a method in Smalltalk. For example,
Classname>>method: anObject
self anotherMethod: aClass with: anObject.
Classname>>anotherMethod: aClass with: anObject.
|instance|
instance:= aClass new: anObject aMessage. //supposing "new:" is the instance method of aClass.
instance aMethodFromTheClassRecieved.
Yes. Classes are just objects.
If you have:
Classname>>anotherMethod: aClass
^ aClass new.
and you execute something like:
instance anotherMethod: OrderedCollection
Then you'll get an instance of OrderedCollection.
In Smalltalk classes are objects too, so if you do OrderedCollection new you actually sent #new message to OrderedCollection class object. So you can pass classes around just like the other objects.
P.S. The main idea of Smalltalk is that it's highly dynamic and live. You can try the thing you are asking about in just 2-5 minutes, and see if it works :)
Related
I try to implement a specific Dictionary class in Smalltalk which needs to override the #at:put: method in Pharo and Squeak. But when I create a class having #at:put: as an instance method and I send that methode, I get the error:
Error: Instances of '#SortedDictionary' class are not indexable
The class definition is as follows:
Dictionary subclass: #SortedDictionary
instanceVariableNames: 'index'
classVariableNames: ''
category: 'MyApplication'
An instance is created by overriding new:
!SortedDictionary class methodsFor: 'creation' stamp: 'nanitous 9/28/2015 19:17'!
new
super new.
^self initialize! !
An instance is initialized with:
initialize
index := Heap new.
^self
And the instance method is defined as:
at: anIndex put: aValue
index add: anIndex.
^self at: anIndex put: aValue! !
And I test with the script in a workspace:
| d |
d := SortedDictionary new.
d at: 1 put: 3.
I tried to make a class not derived from #Dictionary but from #Object and used an instance variable dict containing an instance of #Dictionary, but with the same result.
Why can't I override #at:put: and and how can I override this method?
EDIT
Thanks to #lurker and #aka.nice I should have done the following:
!SortedDictionary class methodsFor: 'creation' stamp: 'nanitous 9/28/2015 19:17'!
new
^super new initialize! !
Doing this wrong was outright silly! In the original and wrong code I was trying to index a nil object.
And:
!SortedDictionary instance methodsFor: 'accessing' stamp: 'nanitous 9/28/2015 19:17'!
at: anIndex put: aValue
index add: anIndex.
^super at: anIndex put: aValue! !
Well, I never came to solve this one before solving the #new issue.
Thanks again to everyone taking the trouble to help out here!
Generally, an instance of collection (more precisely a subclass of Collection) is created with #new:, not #new.
The parameter passed to new: is a size, either the size for a fixed size collection (like Array new: 3), or some pre-allocated size for variable size collection (like OrderedCollection, Set, Dictionary, ...).
From the stamp, I guess you are on a Squeak or Pharo flavour, so I will continue explanation with these dialects, it may slightly vary for other flavours.
In Squeak/Pharo, see the definition of HashedCollection class>>new:
new: nElements
"Create a Set large enough to hold nElements without growing"
^ self basicNew initialize: (self sizeFor: nElements)
It sends initialize: not initialize.
So the first thing you have to do is to define initialize: at instance side of your class, and the second thing is to remove definition of new/new: overriding these is rarely ever needed in Squeak/Pharo.
Currently you have a problem in your #new definition, when you tell self initialize what is self exactly? it is the class SortedDictionary, so you initialize the class, not the instance! And you answer the class, not the newly created instance, so you later send at:put: to the class...
It should have been something like newInstance := super new. ^newInstance initialize.
Last, your at:put: definition will loop forever, it should invoke super at: ... put: ...
A couple of nits to pick.
When you write Smalltalk code as text, such as we're doing here,
you can use the format
{classname|blank} {class|blank} >> methodHead
where the first field names the class, the second field tells whether it is class side or instance side, and the '>>' indicates start of source code.
If you don't name the class, we assume the same class as the last one named.
If you don't say it is class side, we assume it is instance side.
So your methods would be written as
SortedDictionary class>>new
^super new
initialize
>>initialize
index := Heap new
>>at: anIndex put: aValue
index add: anIndex.
^super at: anIndex put: aValue
Second, since you're defining a subclass, you only need to define
your own #new (and/or #new:) method if you must override the one that is otherwise inherited from the superclasses. (But you knew that).
Third, whenever you write an #initialize method, you want to get in the habit of writing 'super initialize.' as the first line thereof.
And once you get into said habit, you'll want to get out of the habit of writing your #new methods starting with '^super new initialize', and get into the habit of starting them with 'self basicNew initialize' instead.
I know, everyone learns to do it that other way. (Sigh.)
But that is soooooo wrong.
Extra points if you can figure out why this is so. ;-)
Hey so I am new to Xcode and I have a few questions.
I want to make a Grade-book Application, that implements quite a few classes. For example, I created a class called "AssignmentList" which basically stores a list of assignment grades in the form of a double.
Another class, called "Course" has a NSMutableArray of AssignmentList objects.
If I wanted to retrieve an AssignmentList parameter for a course, my Java instinct would tell me to make a getter method like this:
-(AssignmentList)getAssignmentList(Course);
However, I can't seem to do that in Objective C, and only works when I do this:
-(id)getAssignmentList(Course);
How do I go about this? I wanted to create a UITableView listing all the AssignmentList objects of a Course, but I can't even set a UITableViewCell with the name of the AssignmentList because it won't let me use the getName method I made, because getName only works for an AssignmentList object, but the getAssignmentList method returns an (id).
Assuming an AssignmentList is a class with instances and not some kind of collection (e.g. an NSArray of Assignments), then your declaration needs to be something like:
-(AssignmentList *) getAssignmentList:(Course *) course;
The * is important: in Objective-C you don't really pass around objects, you pass around pointers to objects. (Well, that's true in Java, too, but you don't have to be explicit about it.)
When you declare something id that means pointer to something of unknown type so you don't need the *.
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.
I'm using Pharo 3.0
Is there a way to remove all objects from memory? I've tried closing and re-opening my image, but it appears that everything is still in memory.
For example, I had:
General Ledger --> Spending Manager and both setup as a singleton:
GeneralLedger>>new
instance isNil ifTrue: [instance := super new].
^ instance
SpendingManager>>new
instance isNil ifTrue: [instance := super new].
^ instance
and messed up somewhere along the way when instantiating Spending Manager - i.e., I returned the instance of General Ledger and not the instance of Spending Manager I guess?
Now when I load my image and try to do CTRL+P on:
spnder:=SpendingManager new. I get:
spnder:=SpendingManager new. a GeneralLedger
I've even removed the inheritance from SpendingManager so that it now inherits from Object, but this still happens.
How did you declare instance?
In such case it should be declared like this:
YourSUperClass classInstanceVariables: 'instance'.
Maybe you did it correctly, but it's unclear from your post (and the hierarchy between your two classes is unclear too).
Your main problem is the usage of super new.
When you create an instance of the subclass for the first time, it will send super new which will:
either return an already initialized instance of superclass
or register an instance of the subclass as the superclass singleton
You should use instance := self basicNew initialize instead.
Also you can write the whole thing
^instance ifNil: [instance := self basicNew initialize]
The other possibility is just to NOT redefine new in subclass, the new from superclass will just work.
And last thing, to remove the initialization, just inspect the class and modify the 'instance' class instance variable directly from the Editor (select this field, type nil and accept).
From reference: Can someone explain what a delegate is with an example?
NICK wrote:
For example, class A asks you for a
delegate. You tell it [this] instance
of class B will do.
[a setDelegate:b];
What is a? Is it a instance of Class of A?
Sending messages to objects using Objective-C is done using the square brackets.
You have instance methods, they are denoted with a - (minus) sign ahead of the return type of the method, like so:
- (void)setDelegate:(id <SomeDelegateProtocol>)delegate;
Alternatively you have the class methods denoted with a + (plus) sign:
+ (NSArray *)arrayWithObject:(id)object;
The first text within the brackets stands for the receiver of that message, in case of an instance message this will be an object pointer. Otherwise, when you deal with a class message, you use the class it's name.
So a is indeed a pointer for an instance, probably of class A (well, it actually is just the name of the variable the object is assigned to. It can be of any class).
This example is presuming that we have two classes, class A and class B, and that we have one instance of each of them; a is an instance of A, and b is an instance of B:
ClassA *a = [[[ClassA alloc] init] autorelease];
ClassB *b = [[[ClassB alloc] init] autorelease];
We're also presuming that class A has some kind of delegate variable, and a method setDelegate: that changes the value of that variable. In general, a delegate is an instance of an object that receives messages about another object's activities or defines its behavior in some way. So, for example, if class A has some method doFoo, class B might have a delegate method a:didFoo: that gets called from class A whenever it does Foo.
But before the delegate can fulfill its purpose, the object it's to receive messages about has to know that it has a delegate. So we have to set our instance of class B as class A's delegate by using class A's setDelegate: method:
[a setDelegate:b];
The short answer is:
Yes.
Hope that clears things up.
For longer answers see Tim & JoostK.
If you're not familiar with Obj-C's message passing syntax you should probably get more practice with that before worrying about delegates. Once you understand message passing, delegates are straightforward.