I'm trying to call a function from another class (Binario) but it says it's not implemented.
This is the code for the method in Binario class:
genlista
^ (1 to: 30) collect: [ :i | 2 atRandom - 1 ]
And this is the code for the other class method:
ListadelistasBin
| bin |
bin := Binario new.
^ (1 to: 30) collect: [ :i | bin genlista ]
Please, help me :(
Most likely #Uko is right and you defined the method in the class side of Binario rather than in the instance side. One way to check this would be to modify your second method like this:
ListadelistasBin
| bin |
bin := Binario. "<- new removed"
^ (1 to: 30) collect: [:i | bin genlista]
If now you get the answer, then what happened is that your genlista method is in the wrong place (class side instead of instance side).
In Smalltalk every method belongs in a class. However, there are two "sides" of a class. The instance side is where you put methods for the instances of the class. The class side is where you put methods for the class itself.
How can you tell in what side of a class you have saved a method? Just look for the switch that every browser has to select one or the other side. In Pharo, for example, there is a toggle button that you use to select each of the sides.
While instance methods define the behavior of the instance of your class (and subclasses), class methods are meant to be sent to the class. This is just a consequence of classes being objects. For example, Binario new is a message sent to the class Binario, and we believe that your intention was to define the genlista method for instances of Binario. If this is the case, then copy the source code of the method and paste it on the instance side of the class. Then remove the class method and try again. Ah! and don't forget to put the new message back next to Binario in your ListadelistasBin!
Related
I created a class named Die (singular of Dice) and set an instance variable side.
Object subclass: #Die
instanceVariableNames: 'side'
classVariableNames: ''
package: 'MyPackage'
I initialized the side variable to 6 by default:
initialize
side := 6.
However I would like the ability to change the instance variable after the object has been created, like so:
myDie := Die new.
myDie side: 10. " it doesn't to work "
It seems to me that instance variables can only be changed by class methods. Is there a way to change it like above?
Also, I have a method roll that returns a random number between 1 and the specified side. If I create two dice and want to roll two dice at the same time, or maybe three dice at the same time, should I create a different class, something like papercup feed that with the number of dices and implement the roll method on the papercup instead?
Thank you.
You are on a right track. When you execute
myDie side: 10.
You send a message side: to myDie which is an instance of a class Die. To "respond" to this message, the class die (or its superclasses) should implement a side: method. Ideally, this method is going to look like this:
side: aNumber
side := aNumber
You see, pharo takes encapsulation very seriously, so instance variables can be directly accessed only by the object itself, and not by anyone from the outside. This is why you always have to create accessors, which is a good practice followed to a various extent by many programming languages.
Regarding your second question: it's a good idea to have a Papercup class, but if you don't need extensive features, the exact task can be achieved by the following code:
papercup := OrderedCollection new.
papercup
add: die1;
add: die2;
add: die3.
papercup collect: #roll
This way you will roll all the 3 dies and return a collection for 3 numbers (collect: is the same as map() in many programming languages). I provided a shorthand version, whereas the full way to write a collect is: papercup collect: [ :die | die roll] when you specify a complete block (closure) and send the roll message to each die.
how can I get a list of all the methods an object can understand?
for example:
set := 8 getAllMethods
will give me all methods 8 can understand in set
In code you can use allSelectors:
set := 8 class allSelectors
gives you a set of all the names of messages (a. k. a. selectors) that 8 can understand.
If you need the CompiledMethods instead of only the message names, you can use lookupSelector:
| class |
class := 8 class. "will be SmallInteger"
set := class allSelectors collect: [:each | class lookupSelector: each]
If you don't want to do this in code but rather find out in the IDE which messages an object can understand, then I propose to use the protocols browser (a. k. a. Lexicon tool). You can open it via "browse protocol" from the context menu of a class:
I used it to find allSelectors and lookupSelector:, which are inherited from Behavior and not defined in Class itself.
This is interesting because of the following. At first glance one might be tempted to consider an expression like this one
anObject class withAllSuperclasses gather: [:class | class methodDictionary]
which gathers all the methods implemented in the class and its superclasses. However, if a method is defined in a class and in one of its superclasses, we should ignore the latter because anObject will use the one in the class.
To remedy this side-effect of the above script we need to gather only the methods that are defined in the class which is closer to anObject class. One way to do this is to enumerate the classes from top to bottom, adding all their methods to a Dictionary. Since the dictionary will only retain the last element added to a given key (in this case a selector), only the ones that belong in the protocol of anObject will survive:
methods := Dictionary new.
anObject class withAllSuperclasses reverseDo: [:class |
methods addAll: class methodDictionary associations].
Note the use of reverseDo: for enumerating the classes downwards.
Another approach would be to enumerate the classes from bottom to top, checking whether the selector has already been visited:
methods := Dictionary new.
anObject class withAllSuperclasses do: [:class |
class methodDictionary do: [:cm |
methods at: cm selector ifAbsentPut: [cm]]]
(were cm stands for CompiledMethod)
The second version is a bit longer, more complex (it has two loops, one nested inside the other) and needs conditional logic (#at:ifAbsentPut:). In other words, it shouldn't be the one chosen.
Note
When looking for ways to create a collection (in this case the collection of all methods understood by an object), first make sure you really need such a collection. For instance, you will need the collection if you want to display it on the screen. However, if you are only going to use the collection for membership checking, there might be other ways to proceed. In your case, you could simply ask the object:
anObject respondsTo: <selector>
and in case the answer is true, recover the method using
anObject class lookupSelector: <selector>.
This is both simpler and more efficient because it doesn't create collections, etc.
Let's say we have a Class and we instantiate it, creating an Instance of that Class. This Instance has a number of (instance)variables, defined by the class, that I need to use. I'd like to get all these (instance)variables in an Array or some Collection so I can iterate through them and set them to some value, not nil.
How can I do this?
I would like to build up on #Uko's answer because there is a more direct way to implement his idea.
The message instSize sent to a Class will answer the number of named instance variables of its instances. This, of course, would include instance variables defined in superclasses.
For instance, RemoteTempVectorNode instSize answers with 17 (wow!). Therefore you could do:
fields := (1 to: anObject class instSize) collect: [:i | anObject instVarAt: i]
and then, change them with:
values withIndexDo: [:v :i | anObject instVarAt: i put: v]
where values is the array of new values you want to inject into the object.
So, why I'm suggesting this instead of instVarNamed:? Because the latter is indirect. If you take a look at its implementation you will see that it has to first find out the name of the i-th ivar by sending instVarIndexFor:ifAbsent: to the object's class. In other words, if you need the ivar names, follow #Uko's suggestion; otherwise don't bring them into the equation because they will only add CPU cycles to your program.
One more thing. As #Sean DeNegris wisely raised in his comment to your question, it would be beneficial if you elaborated a little bit more on why you need such an unusual maneuver.
EDIT:
Now that Pharo has Flexible Object Layouts the mapping between inst var names and the class instSize is no longer valid (in classes that use the new capability.) So, the simpler approach of using just indexes would not work with generality. In fact, under the new "taxonomy" the instSize (number of fields) of an object may be different from the #numberOfInstanceVariables. I guess that the added flexibility has its costs and benefits.
You can send #allInstVarNames to a class (Behavior) to get names of all instance variables defined by it and by superclasses. If you need without superclass variables, you can use #instVarNames
Let's say that var is your variable that you need to work with. Then you can get the collection of instance variable names and iterate them.
You can use #instVarNamed:put: to set instance variable by name, and #instVarNamed: to get the value by name (in case you need).
I think that something like this may help you:
var class allInstVarNames do: [ :instVarName |
var instVarNamed: instVarName put: <yourValue>
What's the difference between the child of a class and an instance of a class? Both seem to inherit code from their "parent". Is the difference that an instance of a class is executed code, versus a child of a class merely being around to create additional instances?
A class is nothing more than a definition, a template, a pattern. An instance of that class is a copy of that definition that has been allocated memory space in which to hold its data. It's like saying a cake is an instance of a cake recipe.
A child of a class is literally that - the parent forms a base definition, which the child then extends or enhances. It's a variation on the parent, much like a chocolate cake is a variation (or it extends) a basic cake recipe.
Note that this very simple explanation of OO concepts hides how this stuff is actually implemented at the machine level. A class can contain methods (operations) - there is only one copy kept of these methods, instantiating a new instance of the class doesn't make a fresh copy of the methods. Instead memory space is allocated to the new instance, and pointers will be used to point to the actual code that should be implemented for each method. Each instance does have its own copy of data (attributes) though.
For example with php:
class A {
//...
}
class B extends A {
//...
}
$a = new A();
We say B is the child of A, $a is an instance of A.
I am using classes and static methods to 'scope' functions in a namespace, similar to C#. However, every time I add a new method to a class, at first it is not found. I have to restart the MATLAB environment (2007a) for the new methods to be recognised.
Surely there is an 'update' or 'refresh' type command that I can use so that I do not have to restart the MATLAB environment each time I add a function?
Issuing this call to CLEAR should do it:
clear classes
One unfortunate side effect of this is that it also effectively issues a clear all, which clears all of the variables in the workspace as well (however, this would happen anyway when you close and restart MATLAB). This clearing of the workspace actually serves a purpose, since it will remove any variables of the same type as the old version of your class, which potentially wouldn't work correctly with the new version of your class.
The function REHASH may work, but I doubt it (I think it deals more with file paths than class definitions).
Clearing instances of your class should work.
Suppose that you have an instance of "MyClass" in your base workspace:
foo = MyClass;
Now, suppose you edit MyClass and add new static method "bar":
foo.bar(); % Will cause error, as foo is instance of previous "MyClass"
However, "clear"-ing foo will remove the reference to the previous class:
clear('foo');
foo = MyClass;
foo.bar(); % this should now work.
This should be fine if you only have one or two instances of the class in your base workspace. If you have many instances of the class in your base workspace, then you may want to write a script to clear them:
varList = whos;
for iVar = 1:numel(varList)
if isequal( 'MyClass', varList(iVar).class )
clear( varlist(iVar).name );
end
end
clear('varList');
clear('MyClass');
If you have instances of the class in more locations, you may wish to extend the script as appropriate.
The last call to clear the class name might only be necessary if you are making modifications to classes in an inheritance hierarchy.
try "clear classname"