next up previous contents
Next: Constants (the attribute final) Up: Data encapsulation with classes Previous: Data encapsulation (public and   Contents

Static components

A C program is a collection of functions, all at the same level and hence all on an equal footing. To unambiguously designate where the computation starts, we insist that there is always a function called main where execution begins.

In a purely object-oriented language, a program is a collection of classes. Every function and variable that is defined in the program must lie within some class. However, as we have seen, classes are just templates and their definitions come to life only after they are instantiated using new. Initially all classes are inactive and there is no way for the program to get started--effectively, the program is deadlocked.

So, there is a need to be able to define functions whose existence does not depend on a class being instantiated.

There is another reason for having such functions. Consider, for example, routine functions like read and write (or scanf and printf, in C terminology), or, for example, mathematical functions like sin, sqrt, ...Clearly, it makes no sense to have to artificially instantiate a class in order to use such functions.

One way to get around this problem without introducing free floating functions that live outside classes (as happens, for instance, in C++) is to add the qualifier static. A function that is marked static inside a class is available without having to instantiate the class. We could have a definition of the form

  class IO {
    public static ...  read(...) { ... }
    public static ...  write(...) { ... }
    ...
  }

and then invoke these functions from outside as IO.read(...) and IO.write(...).

Static functions also solve the problem of where to start--like C, we can insist that the collection of classes includes one static function with a fixed name (say, main, like C) and begin execution by invoking this method.

In addition to static funtions, it also makes sense to have static data variables. This can be used to define constants, such as:

  class Math {
    public static double PI = 3.1415927;
    public static double E  = 2.7182818;
    public static double sin(double x) { ... }
    ...
  }

Notice that the designation static is orthogonal to public/private. Does it make sense to have something that is private static?

Though it appears useless at first sight, we could consider a class all of whose instances needs some ``magic numbers'' to do their job, but where these ``magic numbers'' need not be visible externally. Suppose we write a class that computes the annual interest yield on a fixed deposit. Typically, the rate varies depending on the length of the deposit, but it might be that all the variable rates are computed from a single base rate. We might then write

  class interest-rate {
    private static double base_rate = 7.32;

    private double deposit-amount;

    public double threemonth-yield(){ ... }  /* uses base-rate
                                                and deposit-amount */ 
    public double sixmonth-yield(){ ... }    /* uses base-rate 
                                                and deposit-amount */ 
    public double oneyear-yield(){ ... }     /* uses base-rate */ 
                                                and deposit-amount */ 
    ...
  }

The idea is that all instances of interest-rate share a single copy of the static variable base_rate, so that there is no unnecessary duplication of data and also no inconsistency.

Static variables are shared across all instances of a class. Thus, we can also use static variables to keep track of global information such as how many times a given function is called across all instances of the class. For example, we could write

  class stack {       
    private int values[100];      /* values are stored in an array */
    private int tos = 0;          /* top of stack, initialize to 0 */

    private static int num_push = 0;  /* number of pushes across all
                                         stacks */

    push (int i, ...){    /* push i onto stack */
      values[tos] = i;
      tos = tos+1;        /* Should check that tos < 100!! */
      num_push++;         /* update static variable */
    }

    ...
  }

Here again, it makes sense to have num_push restricted to be private because we want it to be incremented only by the method push within the class stack.

We have to be careful when we mix static and non-static entities in the same class. A non-static function is tied to a specific instance (object) and so can implicitly refer to the current state of the object as well as to static data (such as the yield functions above).

However, since a static function is shared amongst all instances of a class (and there need not even be a single instance in existence for the static function to be used), such a function should not make any reference to any non-static components of the class. We will address this point in more detail later.


next up previous contents
Next: Constants (the attribute final) Up: Data encapsulation with classes Previous: Data encapsulation (public and   Contents
Madhavan Mukund 2004-04-29