问题
Basically I can use variables just by assigning something to them, for example:
x := something
It works fine.
But in classes, if I define a new method, but I don't declare the variable, I get an "assignment to undeclared variable x", so I have to use:
|x| x := something
Why is this?
回答1:
As Uko mentions, there are different kinds of variables in Smalltalk and that's why we need to declare them differently. Let's review all of Smalltalk variables here for the sake of completeness.
Instance variables
Meaning: These are the ones that define the shape of the class. For example, the class Point
defines the ivars x
and y
.
Declared: In the class definition.
Scope: Local, restricted to every instance.
Case: usually lowercase.
Class variables
Meaning: These variables are shared among several objects. They are not global though.
Declared: In the class definition.
Scope: Shared by the class, its metaclass, all subclasses, their metaclasses, all instances and all subinstances.
Case: usually Uppercase.
Class instance variables
Meaning: Are instance variables of the metaclass and therefore determine the shape of the class (not of its instances).
Declared: In the class definition.
Scope: Local, restricted to class-side methods.
Case: usually lowercase.
Temporaries
Meaning: These are auxiliary variables used in methods and blocks. They get allocated in the execution stack every time the method is activated (expect for those declared in a method or block closure and used in an inner block).
Declared: Between pipes as in | temp |
at the beginning of the method's (or block) body.
Scope: Activation of the method or block.
Case: usually lowercase.
Pool variables
Meaning: Are held in global PoolDictionaries
and can be used in any class that declares their use.
Declared: The class declares the usage of the PoolDictionary
that defines them.
Scope: The class and all subclasses and metaclasses.
Case: usually Uppercase.
Global variables
Meaning: Are shared by every object in the system.
Declared: Nowhere. They are defined in the Smalltalk system dictionary by meas of Smalltalk at: <GlobalSymbol> put: <an object>
. Once declared their value can be changed using :=
.
Scope: The entire image.
Case: usually Uppercase.
Remark: Class names are global variables. However, you should not assign them using :=
(unless you know what you are doing.)
Pseudo variables
Meaning: They can be read but not written. These are: self
, super
, true
, false
and nil
.
Declared: Nowhere.
Scope: Can be used everywhere. However, the meaning of self
and supper
changes with the object that uses them.
Method and Block Arguments
Meaning: They represent the formal arguments that the method or block will accept (and require) at every activation.
Declared: In the method signature or the beginning of the block.
Scope: The method or block that declares them.
Case: lowercase.
Workspace variables
Meaning: These are variables associated to workspaces (Playground in Pharo).
Declared: Usually not explicitly declared (the workspace will declare them behind the scenes).
Scope: The life of the workspace.
Case: lowercase.
回答2:
x := something
is allowed for scripting reasons. It, in fact, creates a variable x
for your script. Now if you write x
in a method without an explicit declaration, which kind of variable should be created? A temporary variable, or an instance variable, or a class variable, or a pool variable, or maybe a global binding? To avoid such issues you have to declare a variable somewhere and then use it.
There is another strategy used by different other languages, such as prefixing a variable with @@
if it has to be a class variable. But this introduces ugly syntax, limits your naming freedom, etc…
来源:https://stackoverflow.com/questions/42459603/smalltalk-variables-why-should-i-declare-them