Partial classes have no associated type and contain code that may only be included by other classes. Partial classes may not be instantiated: no routine calls from another class into a partial class are allowed, and no variables may be declared in another class of such a type.
A stub feature may only be present in a partial class. They have no body and are used to reserve a signature for redefinition by an including class. If code in a partial class contains calls to an unimplemented method, that method must be explicitly provided as a stub. The following class is a stub debugging class which checks on the value of a boolean and then prints out a debugging message (preceeding by the class name of 'self')
partial class DEBUG_MSG is
stub debug:BOOL;
debug_msg(msg:STR) is
-- Prints out the type of "self" and a debugging message
if not debug then
-- Don't print out the message if the debug flag is false
return;
end;
type_str:STR;
-- Declared here since used in both branches of the if
if ~void(self) then
type_id:INT := SYS::tp(self);
-- SYS::tp will not work if self is void!
type_str:STR := SYS::str_for_tp(type_id);
else
type_str := "VOID SELF";
end;
#OUT + "Debug in class:" + type_str + " " + msg + "\n";
end;
end; |
This class can be used by some other class - for instance, a main routine that wants to print out all the arguments to main. The stub routine 'debug' must be filled in using either an attribute (a constant, in this case) or a routine.
class MAIN is
include DEBUG_MSG;
const debug:BOOL := true; -- Fill in the stub.
main(args:ARRAY{STR}) is
loop
arg:STR := args.elt!
debug_msg("Argument:"+arg); -- Print out the argument
end;
end;
end; |
Partial classes cannot be used to instantiate parameters of a parametrized class. For example, 'ARRAY{DEBUG_MSG}' would not be legal.
Create cannot be called on a partial class, nor can a partial class occur as the type of a variable or attribute.
This code demonstrates the use of partial classes. Each MIXIN class provides a different way of prompting the user; each can be combined with COMPUTE to make a complete program. The stub in COMPUTE allows that class to be type checked without needing either mix-in class. Only COMPUTE_A and COMPUTE_B may actually be instantiated.
Now suppose that we have a 'COMPUTE' class that requires a prompt for some input data. It can leave the prompt routine as a stub, which will later be filled in by some prompt class
partial class COMPUTE is
stub prompt_user:STR;
main is
res ::= prompt_user;
-- Convert it to an integer and do something with it
i:INT := res.cursor.get_int;
#OUT + "I'm going to compute with this number, now:" + i + "\n";
...
end;
end; -- partial class COMPUTE |
We can now create different computation classes by mixing an arbitrary prompt style with the main computation partial class.
class COMPUTE_A is include COMPUTE; include PROMPT_STYLE_A; end; -- class COMPUTE_A class COMPUTE_B is include COMPUTE; include PROMPT_STYLE_B; end; -- class COMPUTE_B |