GEOS SDK TechDocs
|
|
4.2 Non-relocatable Data
|
4.4 Declaring Objects
@method, @extern
Methods are the routines executed when an object receives a message. Each class understands a certain set of messages; each of these has a place in the class' method table and corresponds to one method.
Although methods are class-specific, they are not defined between the
@class
and
@endc
of class definition. Instead, their declaration line links them to a single class and to a specific message. Goc, Glue, and GEOS build each class' method table automatically; you do not have to create the table yourself.
To define a method, use the
@method
keyword. This has the following structure:
@method [<hname>,] <cname>[, <mname>]+;
MyClass
' handler for
MSG_DO_SOMETHING
"MyDO_SOMETHING".
_reloc
, used in place of a message name when writing a method for
MSG_META_RELOC
and
MSG_META_UNRELOC
. A method handling
_reloc
will handle both
MSG_META_RELOC
and
MSG_META_UNRELOC
; the method code can check the value of its message argument to find out which message is being handled.
Note that the name of the method (the handler name) is optional. Parameters and return values are not put in the method declaration--these are defined with
@message
as discussed in The GEOS Message System
.
If you will wish to call the method as a routine occasionally, your compiler will probably require that you provide a prototype for the routine. If your
@message
declaration looks like
@message word MSG_MC_DO_SOMETHING(word thing);
and your
@method
declaration looks like
@method DoSomething, MyClass, MSG_MC_DO_SOMETHING {
/* Code Here */ }
Then your protoype should look like
extern word _pascal DoSomething(optr oself, MyMessages message, word thing);
The name of the type
MyMessages
is constructed automatically by taking the name of the class, removing the "Class" suffix, and replacing said suffix with "Messages".
Normally, all of a class' methods will be coded in the same code file in which the class is declared with
@classdecl
. If, however, you find you need to declare a class' methods in a different file, you can use the
@extern
keyword to indicate a method is defined and/or used in a different object file. Goc will give no error if
@extern
is used and the method exists nowhere; Glue, however, will give a linking error in such a case. There is no such requirement, however, if you are putting only the class definition (the definitions between
@class
and
@endc
) in a different file. In this case, you can put the class definition in a
.goh
header file and the method code in the same
.goc
file as the
@classdecl
statement; you must
@include
the
.goh
file, but you won't need to use the
@extern
directive (as long as the method code is in the same file as the
@classdecl
directive).
The format for using
@extern
is as follows:
/* In the file in which the class is declared with * @classdecl:
*/
@extern method <cname>, <mname>+;
/* In the file containing the method code: */
@extern method <cname>, <mname>+ {
...method code goes here...
}
Three parameters are passed automatically with messages and do not have to be declared in the
@message
definition. They are important to know when writing methods, however, because they can greatly simplify your code. These are standard parameters for all classes except
ProcessClass
and its subclasses below:
@self
, instead. Unlike pself,
@self
is always valid.
As mentioned,
ProcessClass
is a special type of class. It has no true instance data because it uses the standard PC structure of an application (idata, udata, etc.). It only has one standard parameter to each of its methods: the message that was sent to it. This is because the "instance data" of
ProcessClass
includes all the global variables of your program. They are accessed automatically, no oself or
@self
is required.
Code Display 5-14 A Class Definition
/* The class ValClass defines four messages that invoke four different methods. The * entire class is shown in this example; it will function properly if coded this * way. Note that the methods have the class name in their declaration line * and thus do not appear within the class definition. */
@class ValClass, MetaClass;
@instance int value; /* instance data value: an uninitialized integer */
/* message declarations * All four messages will be handled by this class. They return * the types shown and take the parameters defined. */ @message int MSG_VAL_GET_VALUE(); @message void MSG_VAL_SET_VALUE(int newValue); @message void MSG_VAL_NEGATE_VALUE(); @message Boolean MSG_VAL_IS_VALUE_BIGGER_THAN(int newValue);
@endc @classdecl ValClass; /* the class structure must be put in memory */
/* Method Declarations * Each of the four methods is a single line of code. Note that the * parameters are automatically defined in the message definition and do * not need to be restated in the method definition. The same is true of * the return type. Note also that the class and message names appear in * the @method line. */
@method ValGetValue, MyClass, MSG_VAL_GET_VALUE {
return(@self->value);
}
@method ValSetValue, MyClass, MSG_VAL_SET_VALUE {
@self->value = newValue;
}
@method ValNegateVal, MyClass, MSG_VAL_NEGATE_VALUE {
@self->value *= -1;
}
@method ValClass, MSG_VAL_IS_VALUE_BIGGER_THAN {
/* This handler's name will automatically be created to be
* ValVAL_IS_VALUE_BIGGER_THAN. You can use this name as a
* C function call from within the same thread. */
return(@self->value > newValue);
}
You may sometimes wish to call a method with normal C call-and-return conventions, rather than by sending a message. To do so, you will have to declare the method as a routine as well as a method. The declaration should have the following format:
extern <type> _pascal <MethodName>( optr oself, <TruncatedClassName>Messages message, <type1> <arg1>, <type2> <arg2>)
Code Display 5-15 Declaring a Method As a Routine
@message int MSG_HELLO_COUNTER_RECALCULATE_VALUE( \ HelloPriority priority, \ word randomDatum, \ char aLetter);
extern int _pascal HelloCounterRecalculateValue( optr oself, HelloCounterMessages message, HelloPriority priority, word randomDatum, char aLetter);
@method HelloCounterRecalculate, HelloCounterClass, \
MSG_HELLO_COUNTER_RECALCULATE_VALUE {
/* method code goes here... */
}
GEOS SDK TechDocs
|
|
4.2 Non-relocatable Data
|
4.4 Declaring Objects