Next: Control structures, Previous: Externs, Up: C [Index]
In many cases, it’s obvious which class an object is, even when the
object’s defition is removed from the place where a program needs to
perform an operation on it, or the object is aliased to self or
to a C variable, or you need to use a different type of language
semantics with an object.
If a program has a set of expressions, as in this hypothetical example:
Integer new myInt;
myList new myList;
Key new myKey;
Symbol new *intPtr;
*intPtr = Integer new "Int 1", "1";
myList push *intPtr;
*intPtr = Integer new "Int 2", "2";
myList push *intPtr;
myKey = myList + 1;
myInt = *myKey;
myInt += 3;
... do stuff with myInt ...
myList map {
printf ("%d\n", self value);
}
When run, the program would produce output like this.
$ ./myProg 1 2
That’s because the changes to myInt would not take effect for
the member of ‘myList’, because Integer objects, when a
program assigns values to them, normally assigns the value of one
Integer to another. However, in the example above, you might
want to work on the original list member - that is, you want the
assignment to treat myInt as if it were a reference.
One way to notify Ctalk of this is to use an Object to refer to
the list element, and use a class cast to notify Ctalk that the
Object is actually an Integer.
Then the program example above looks like this.
Object new myIntObject;
myList new myList;
Key new myKey;
Symbol new *intPtr;
*intPtr = Integer new "Int 1", "1";
myList push *intPtr;
*intPtr = Integer new "Int 2", "2";
myList push *intPtr;
myKey = myList + 1;
myIntObject = *myKey;
(Integer *)myIntObject += 3; /* The cast tells Ctalk to treat myIntObject,
which is declared as an Object,
as an Integer, so it can work correctly
with the first element of myList. */
... do stuff with myIntObject ...
myList map {
printf ("%d\n", self value);
}
Other places that you can use class casting is when a program uses
a C OBJECT *. In that case, you can tell Ctalk what class
the object is. Here’s an abbreviated example from a map method in
TreeNode class.
OBJECT *t, *list_elem;
/* rcvr_obj is a TreeNode object. */
for (t = __LIST_HEAD(rcvr_obj), have_break = NULL;
t && !have_break; t = t -> next) {
list_elem = obj_ref_str ((t -> instancevars) ?
t -> instancevars -> __o_value :
(IS_VALUE_INSTANCE_VAR(t) ?
t -> __o_p_obj -> instancevars -> __o_value :
"0x0"));
... do stuff ...
(TreeNode *)list_elem children __mapChildren methodfn;
(TreeNode *)list_elem siblings __mapSiblings methodfn;
}
This is a convenient way for a program to tell Ctalk that list_elem
is a TreeNode object. It’s up to the program to ensure that the
C variable actually does point to an object of that class, or the program
won’t work correctly at run time.
Programs can also cast self to a class, in cases where Ctalk
cannot determine self's class from its context, like in this
example
myList map {
(Float *)self = 0.01f;
}
This feature is still experimental, and you should use it with caution; in particular, it’s up to the program to insure that the object actually is a member of the class that you cast it to. However, on the occasions when a program needs to excercise some control over a set of expressions’ semantics, then class casting can be useful.
Next: Control structures, Previous: Externs, Up: C [Index]