Friday, April 13, 2007

CLASSES

CLASSES
Class declarations define new reference types and describe their implementation. This chapter dwells on members of a class, class semantics as well as meanings of access modifiers applied to classes and members of classes.

Class declarations: a class declaration defines new reference types. A class declaration can be either a normal class declaration or an enum declaration.
The notation for a normal class declaration is as below:
ClassModifiersopt class identifier TypeParametersopt Superopt Interfacesopt ClassBody

A class declaration is introduced by the keyword class which can be preceded by an optional access modifier. The identifier in a class declaration specifies the name of a class. We’ve discussed names and meaning of names in an earlier blog. If a class declaration has TypeParameters specified, which is optional, then it is a generic class and in a class declaration, only one optional superclass can exist while any number of interfaces, also optional, can be implemented. The ClassBody is enclosed in opening ‘{‘ and closing ‘}’ wherein the codes for class behaviour and storage spaces are defined.

Class Modifiers: more than one class modifier can be specified for a class. The modifiers that can be attached to class declarations are:

public (applied only to top level classes and member classes. )
protected (applies only to member classes)
private (applies only to member classes)
abstract
static (applies to member classes)
final
strictfp

please note that a compile time error will occur if the same modifier appears more than once in a class declaration. If an annotation on a class declaration, a, corresponds to an annotation type, T and T has a (meta-)annotation m such that m corresponds to annotation.Target, then m must have an element whose value is annotation.ElementType.TYPE or a compile time error occurs.

Abstract classes: an abstract class is a class that is considered incomplete. Note that only a class declared abstract is allowed to have abstract methods, otherwise, a compile time error occurs.

Enum types (in a later blog, please) must not be declared abstract, otherwise, a compile time error occurs. An Enum type is only allowed to declare a method as abstract if it has one or more enum constants with class bodies that provide concrete implementation of the abstract method.

A class C can have abstract methods from any of the 3 ways:
- if C explicitly declares an abstract method (remember, from what we discussed, to do this C has to be abstract itself.)
- if any of C’s superclasses have an abstract method and C neither declares nor inherits a method that implements this method.
- a direct superinterface of C declares or inherits a method (interface are necessarily abstract; to be discussed later) and C neither declares nor inherits the method that implements it.

The example in the jls will be restated here, not for redundancy’s sake but to clarify some points explained therein.

package examples;

//Point is declared abstract because it contains
//an abstract method, alert()
abstract class Point {
int x=1, y=1;
void move(int dx, int dy){
x += dx;
y += dy;
alert();
}
abstract void alert();
}

//ColoredPoint must be declared abstract since it
//inherits alert() from Point and doesn't implement it
abstract class ColoredPoint extends Point {
int color;
}

//SimplePoint although subclass of Point is not abstract
//because it implements alert()
class SimplePoint extends Point{
void alert(){
System.out.print("X is now: "+this.x+". ");
System.out.println("Y is now: "+this.y);
}
}

class Loader {

public static void main(String[] args) {
Point p = new SimplePoint();

//field initialisers and methods of Point can
//now be invoked. try it and see.
p.move(2, 2);
}
}

A class is declared abstract with the intent that subclasses can be created to complete the implementation but where one wants to create a class that needs not be instantiated, a better way to do this is to declare the class’ constructor as private, never invoke the constructor, declare it without arguments and declare no other constructor.
Final classes: a final class is a class whose definition is complete and no subclasses are desired or required for it.
Note:
1. a final class can be a superclass of another class
2. a class declared final can never be overridden because it doesn’t have subclasses
3. a class declared final can never be declared abstract

strictfp classes: the effect of modifying a class with the strictfp modifier is to make all float or double expressions within the class declaration to be explicitly FP-strict i.e strictly within the floating-point value set.

Generic Class and Type Parameters: a class is generic if it declares one or more type variables. These type variables are known as the type parameters of the class.
The type parameter section follows the class name and its delimited by angle brackets, ‘<’ and ‘>’. Note that the type parameters are sectioned in the type and their definition is within the generic class declaration. They share the same class at run-time.

Note:
1. generic classes do not throw exceptions i.e they can never be direct or indirect subclasses of the class Throwable.
2. the scope of a class’ type parameter is the entire declaration of the class including the type parameters section itself. Therefore, type parameters can appear as parts of their own bounds, and as bounds of other type parameters declared in the same section.
3. parameterized class declarations can be nested inside other declarations.

I tried to write a little example to this effect.

package examples;

public class Nigeria {
String name, gmt;
}

public class Ghana {
String name, gmt;
}

public class Africa {
//note: the field declaration for this class will be
//within the scope of the type variables
String name, gmt;
Africa(String countryname, String countrygmt){
this.name = countryname; //type has fields in scope
this.gmt = countrygmt;
}
}

class Loader {

public static void main(String[] args) {
Africa naija = new Africa("Nigeria",
"+1");
Africa kwama = new Africa("Ghana", "0");

//the sections in our generic class share same run-time
//class.
boolean b = naija.getClass()== kwama.getClass();
System.out.println(b);

//let's create a nigerian object
Nigeria mortar = new Nigeria();

//type variable Nigeria not same as class type Nigeria,note
System.out.println("Is type variable same as class type?
"+mortar.equals(naija));

//but class type can reference type variable
mortar.name = naija.name;
System.out.println("Mortar took a name which is: "
+mortar.name);

//we're certain now that we have the right name
System.out.println("In a section of africa there is a
country called: "+naija.name);
}
}

(to be continued)

No comments: