< Zurück | Inhalt | Weiter >

3.4.2 Inheritance

Inheritance is how a class places itself in a hierarchy of existing classes. In Java, each class inherits from exactly one existing class. A class names the class from which it inherits with the extends keyword. We said a Java class inherits from exactly one class, and yet our Example 3.24 doesn’t contain the extends keyword. What gives?

If a class doesn’t explicitly extend an existing class, it implicitly extends the “root” Java class, Object. The Object class has some interesting features, and the fact that all Java classes directly or indirectly extend Object has interesting consequences that we will explore later.

Persons coming to Java from another object-oriented language whose name shall remain C++ might wonder about multiple inheritance. Java has the concept of interfaces. An interface is like a class, except that it may not contain data10 and may contain only method definitions, without any implementation (Example 3.25). An interface may not be instantiated (created with the new operator),11 so how do you make use of interfaces? Well, a class extends exactly one existing base class, but it may implement any number of interfaces by using the implements keyword (Example 3.26).



image

Example 3.25 An interface

public interface Identifiable

{

public int getID();

}


image


As you can see, a class that implements an interface must provide an imple- mentation of all the methods defined in the interface. We said that an interface cannot be instantiated, but you can declare a variable of type Identifiable


image

10. Actually, an interface may contain final static data, but since we haven’t introduced these concepts yet, just pretend interfaces cannot contain data for now and we’ll put the lie to it later.

11. Although you can do something that looks suspiciously like it with anonymous inner classes—but since we haven’t introduced these concepts yet, just pretend that you cannot instan- tiate an interface; you will see such use later.


image

Example 3.26 A class that implements an interface

class Sample

implements Identifiable

{

private int id;


public void method()

{

System.out.println(id);

}


public int getID()

{

return id;

}

}


image


and assign an instance of the Sample class to it. In fact, you could assign an instance of any class that implements the Identifiable interface to it.

Interfaces may also have an extends keyword. In other words, an interface may inherit from an existing interface. This may be useful if you know you will want to use methods from both the extended and the base interface without having to cast the object reference. Otherwise extending an interface is unnecessary since a given class may implement as many interfaces as desired.


3.4.2.1 Inheritance and Encapsulation

Encapsulation and inheritance are related to one another and are controlled by access modifiers on classes, data members, and methods. Let’s spend a little time talking about these modifiers and what they mean.

The access modifier keywords are public, private, and protected. When a data member or method is private, it can only be accessed or called from within this specific class. Neither classes that extend this class, nor classes outside this class may access such a data member or call such a method. How- ever, one instance of a class can access private members of another instance of the same class. We don’t encourage such use.

When a data member or method is marked protected, however, the only classes that can access such a data member or method are either 1) classes that extend this class and their descendants, or 2) other classes in this package (even


if they don’t extend this class). Classes in other packages (unless they extend this class) can not get at such members.

A public data member or method may be accessed by any code in any class.

What if you do not put an access specifier on? Then the item (data mem- ber, method, or class) has package visibility. Such an item is accessible to any other class within the package, but no further. Not even derived classes, unless they are in the same package, are allowed to see it.12

In terms of how restrictive the access is, you can think of the terms in order of decreasing strictness as:

private

• (package)13

protected

public



TIP

Beginner Java programmers often declare everything as public, so that they can ignore such issues. But then they get the OO religion, and having experi- enced reliability issues (others messing with their variables) they go to the other extreme and declare private as much as possible. The problem here is that they often don’t know how others will want to reuse their code. Restricting every- thing to private makes reuse more narrow. We prefer using private for data members but protected for those internal helper methods that you might otherwise make private; this hides your implementation from most other classes while allowing someone to override your methods, effectively providing a way for them to override your implementation. Allow those who would build on your work the ability to do so without having to reimplement.

image


Here is a simple example of each type of declaration:


image

12. If you are a C++ programmer, the following description may mean something to you (if not, skip this): All classes within a package are essentially “friends.”

13. Remember there is no keyword for package level protection, rather it is the absence of a keyword that denotes this level of protection. We had to write something in that space on the page so you’d know what we’re talking about.


private String hidn; String pkgstr;

protected String protstr; public String wideOpen;


3.4.2.2 The static statement

Another keyword qualifier on declarations that we need to describe is the static keyword. When a variable is declared static then there is only one instance of that variable shared among all instances of the class. Since the vari- able exists apart from a particular instance of the class, one refers to it with the class name followed by a dot followed by the variable name, as in System.out.

Similarly, methods can be declared static as well. This also means that you don’t need an instance of the class to call them, just the class name, as in System.getProperties().

Now with Java 5.0, you don’t even need the class name, provided that you have a static import statement at the top of your class, for example:


import static java.lang.System.*;


3.4.2.3 The final statement

Another way that static is often seen is in conjunction with the final key- word. When a variable is declared final then a value can be assigned to it once, but never changed. This can make for good constants.

Since public will make the variable visible to all other classes, static will make it a class variable (available without an instance of that class), and final will keep it from being altered (even though it is publicly available), then combining all of those gives us a good declaration for a constant, for example:


public static void long lightSpeed = 186000; // mps


New to Java 5.0 is the explicit creation of enumerated types. Prior to 5.0, programmers would often use static final constants even when the partic- ular value was unimportant, as a way to provide compile-time checking of the use of the constant values. Here is an example of a declaration of a set of enumerated values:


enum WallMods { DOOR, WINDOW, VENT, GLASSBLOCK };




TIP

A common technique used with public static final constants is to put them in an interface definition. (This is the exception to the rule that interfaces define method signatures but contain no data.) When a class wants to use one or more of those constants, it is declared to implement that interface:


public MyClass extends BigClass

implements Comparable, LotsaConstants

{

...

}


In defining MyClass we have declared that it implements LotsaConstants (not a name that we recommend you using). That makes all the constants that we have defined inside the LotsaConstants interface available to the MyClass class. Since classes can implement many different interfaces, this doesn’t interfere with the use of other “real” interfaces, such as Comparable.

image



WARNING

The keyword enum is new to Java 5.0, so older programs that may have used enum as a variable name and will now cause an error when recompiled for Java 5.0.


image

The enum will look very familiar to C/C++ programmers, but there are some important differences. In C/C++ the values of the enum elements are, in reality, integer values. Not so in Java. Here they are their own type, but can be converted to a String via the toString() method, with a value that matches the name, for easy reading and debugging.

Enumerated values can be used in == comparisons since they will be defined only once (like other static final constants) and it would only be references that are passed around. They would be referenced by the name of the enumeration followed by dot followed by the particular value (e.g., WallMods.WINDOW) and used as an object. (We have used uppercase for the names not out of any syntax requirement, but only to follow the typical naming convention for constants.)