Sunday, December 9, 2007

Packages,Access,Interfaces

Packages

A Package is a named group of classes. Generally, the classes of a package are collected together into a directory. It is possible for package classes to appear in more than one directory, but it's hard to imagine when this would be helpful. So a package looks a lot like a directory, even though they aren't exactly the same thing.

There is another similarity: Just as a directory can contain files and subdirectories, a package can contain classes and subpackages. For example, a package called acmeproducts might contain two classes named Database and Connection. The package might also contain a subpackage called utilities, which contains three classes named ThreadPool, Mailbox, and UserProfile.

Access

Java's access control is based on the idea that certain features of a class should not be usable by other classes. Before you learn the details of access control, let's look at why this idea is sound.

To support this data-hiding approach, object-oriented languages provide facilities to let you restrict access to a class's data and methods. In Java, this is done with access modifier keywords. Java has three access modifiers:

  • public

  • private

  • protected


Final and Abstract

This section will look at two more modifiers: final and abstract. They aren't access modifiers, but this is still a good place to present them.

Final

Classes, methods, and data may be designated final. A final class may not be subclassed. A final method may not be overridden. A final variable may not be modified after it is initialized.

Final data is useful for providing constants. For example, you might have a Zebra class that provides the zebra's weight in pounds or kilograms:

class Zebra extends Mammal
{
private double weightKg;

public double getWeightKg()
{
return weightKg;
}

public double getWeightLbs()
{
return weightKg * 2.2;
}
}

This class uses appropriate data hiding. A zebra's weight is stored in kilos (the variable name leaves no doubt there), but users of the class never need to know that. Let's assume that eventually the class will have many methods that convert back and forth between kilos and pounds. There will be a lot of multiplying and dividing by 2.2. The standard approach to this situation is to declare a constant:

class Zebra extends Mammal
{
static private final double KGS_TO_LBS = 2.2;

private double weightKg;

public double getWeightKg()
{
return weightKg;
}

public double getWeightLbs()
{
return weightKg * KGS_TO_LBS;
}
}

The constant is called KGS_TO_LBS. It is static because its value is the always going to be the same for all instances of the class, so there is no benefit in giving each instance its own non-static copy. It is private because it is only for use inside the class. It is final because its value should never change under any circumstances. Constants require a little extra typing, but they are well worth the effort for three reasons:

  • They explain what they do. Someone reading the code, especially someone who doesn't recognize 2.2 as the kilogram-to-pounds conversion factor, will instantly understand the intention of a constant named KGS_TO_LBS.

  • They eliminate the need to look up or memorize conversion factors and similar values.

  • They provide protection against typos.

The third point requires an example. Suppose you aren't using constants, and it's late at night, and you're tired. Somewhere in the Zebra source code, which is now thousands of lines in length, your finger slips and you accidentally type 3.3 instead of 2.2. It could take a long time for the error to manifest itself, and when it does, you will have to soft through thousands of lines of code to find the problem.

On the other hand, suppose you are committed to using the constant. It is still late at night, and your finger slips, and you accidentally multiply by KGS_TO_LBX instead of KGS_TO_LBS. The next time you compile your code, the compiler will complain that variable KGS_TO_LBX does not exist. When you use constants, the compiler finds your typos for you.

Abstract

Classes and methods may be designated abstract; data may not.

An abstract method has no method body. All the code from the opening curly bracket through the closing curly bracket is gone, replaced with a single semicolon (;). Here is an example of an abstract method:

abstract protected double getAverage(double[] values);

The abstract keyword may be combined with the public and protected access modifiers. Here you see a method that is both abstract and protected. There is nothing unusual about the declaration part of the method. It only gets strange after the parenthesis that closes the argument list. Where you would expect to find the method body, there is only a semicolon.

When a class has an abstract method, that method's implementation will be found in the class's subclasses. In a moment you'll see an example, but first let's cover a few rules governing abstract classes and methods.

An abstract class may not be instantiated. That is, you are not allowed to call any constructor of any abstract class. Also, if a class contains any abstract methods, the class itself must be abstract. You might say that an abstract class is one that is incomplete: It lacks one or more method implementations.

Suppose you want to create several classes, all of which share some functionality and model similar real-world things. This strongly indicates that the classes should extend a common superclass, which should contain the shared functionality. Every subclass will inherit the common methods, so this is a good object-oriented design. It would not be unusual at this point to realize that there is some functionality that every subclass must have, but that every subclass should do in its own unique way.

Data in Interfaces

An interface is allowed to contain data, provided the data is public, final, and static. This provides an easy way to define constant data.

Extending Interfaces

An interface is allowed to extend another interface. The syntax is

interface  extends 
{
// Declarations and data
}

The new interface consists of all the methods and data defined in the parent interface. For example, you might define the following:

package nature;

interface SingingTalker extends Talker
{
public void sing(String song);
}

This interface consists of the two methods defined in Talker (say() and repeat()), as well as sing(). A class that wants to implement this interface must use all three methods.

A class can extend only a single parent class, but an interface can extend multiple parent interfaces. For example, if InterA, InterB, and InterC are all interfaces, the following is legal:

interface ManyParents extends InterA, InterB, InterC
{
public int anotherMethod(double d, char ch);

}

This interface consists of all the constants and methods of all three parents, plus the method defined explicitly in the source code.


The API Pages

There are more than 1,000 core Java classes, and every one of them has been described in detail by the Java creators. Unlike a lot of manufacturers' technical specifications, these descriptions are well-written, accurate, and helpful. They are provided as a set of interconnected HTML pages that you can download to your hard drive and view with the Web browser of your choice. Like Java itself, they are freely downloadable. If you have not already done so, please download them before continuing with this chapter.

Digression: A Personal Anecdote

Quite a while ago, before the birth of the World Wide Web, I worked for a company that made computers. These computers used a programming language that was a bit like C, but it was object-oriented. In addition to the language, there were a number of classes that supported I/O, graphical user interfaces, math, and so on. If you saw it today, you would probably be reminded of Java, but with fewer supplied classes.

There were several dozen of these classes. Their documentation consisted of two manuals that listed the classes in alphabetical order. For each class, the manuals listed the inheritance hierarchy, the data, and the methods.

Those of us who wrote programs for this system each had our own copy of the manuals. You could tell how long someone had been working there by the shape their manuals were in. Those books took a beating. We were always flipping back and forth. If I wanted to remind myself what a certain method of a certain class did, I might find that the method wasn't explained where I expected an explanation, because the class I was reading about inherited the method from its superclass. So I would look up the superclass (which might be in the other volume), and I would see that it returned an object reference, and I would have to look up that object's explanation because I hadn't seen it before.

I flipped a lot of pages because a lot of information for one class was (quite rightly) presented in the description of a different class. For example:

  • The class's superclass

  • The type of a non-primitive variable

  • The type of a non-primitive method argument

  • The type of a non-primitive method return value

  • Any class, method, or variable mentioned for any reason in the description I was reading

A set of HTML documents would have eliminated all that page-turning. The only problem was, this was 1988 and there was no HTML. The Web was just a glimmer in the eyes of a few people in Switzerland, and hypertext was an idea that wasn't discussed much outside of universities. We programmers would often wonder, "Couldn't we fix it so I could read all this on my screen, and somehow click on names of classes and data and methods to read their explanations?" But we didn't invent the World Wide Web.

No comments: