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
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
No comments:
Post a Comment