4.2. Partial Classes and Stub routines

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
      -- 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);
         type_str := "VOID SELF";
      #OUT + "Debug in class:" + type_str + " " + msg + "\n";

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
         arg:STR := args.elt!
         debug_msg("Argument:"+arg);    -- Print out the argument

Points to note

4.2.1. Mixins: A Prompt Example

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; -- 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