Partial Classes and Stub routines

Sather - A Language Tutorial
Prev | Chapter 4. Code Inclusion and Partial Classes | Next

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

## Points to note

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

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

Prev | Home | Next
Code Inclusion and Partial Classes | Up | Abstract Classes and Subtyping