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 |