Normal selector invocations determine the method at run-time depending on the class of the receiving object. This run-time selection is called late binding.
Sometimes it’s preferable to invoke a different method. For example,
you might want to use the simple method for print
ing
object
s instead of the possibly long-winded print
method
of the receiver class. You can achieve this by replacing the invocation
of print
with:
[bind] object print
in compiled code or:
bind object print
in interpreted code. Alternatively, you can define the method with a
name (e.g., print-object
), and then invoke it through the
name. Class binding is just a (often more convenient) way to achieve
the same effect; it avoids name clutter and allows you to invoke
methods directly without naming them first.
A frequent use of class binding is this: When we define a method
for a selector, we often want the method to do what the selector does
in the parent class, and a little more. There is a special word for
this purpose: [parent]
; [parent]
selector
is equivalent to [bind] parent
selector
, where parent
is the parent
class of the current class. E.g., a method definition might look like:
:noname dup [parent] foo \ do parent's foo on the receiving object ... \ do some more ; overrides foo
In Object-oriented programming in ANS Forth (Forth Dimensions, March 1997), Andrew McKewan presents class binding as an optimization technique. I recommend not using it for this purpose unless you are in an emergency. Late binding is pretty fast with this model anyway, so the benefit of using class binding is small; the cost of using class binding where it is not appropriate is reduced maintainability.
While we are at programming style questions: You should bind
selectors only to ancestor classes of the receiving object. E.g., say,
you know that the receiving object is of class foo
or its
descendents; then you should bind only to foo
and its
ancestors.