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]