Methods-Defining Behavior

   

Methods ”Defining Behavior

Although variables define the state of a class instance, methods define the associated be havior that controls that state and do the actual work that takes place in your programs. Methods support access specifiers and modifiers in a similar manner to fields. The details of method declarations and syntax were discussed previously in Chapter 4. This section extends that discussion to look at some special uses of methods.

Constructors

A constructor is a special method that is called when a class instance is created. A constructor provides a place for you to define any initialization code you want executed for a new class instance. A constructor is named the same as the class and its declaration looks like a typical method declaration because it can include an access specifier and a parameter list. However, a constructor declaration cannot contain a modifier, a return type, or a throws clause. For example, the constructor for the earlier GeneralAccount class was

 public GeneralAccount( String accountNum ) {   accountNumber = accountNum; } 

Caution

Be careful when you declare a constructor to omit the return type found in regular method signatures. Even if you insert a return type of void, the compiler will interpret what you implement as a normal method and not a constructor.


The Default Constructor

Look again at the StopLight class example:

 public class StopLight{   /* 0 -> Green      1 -> Yellow      2 -> Red    */   int greenYellowRed; } 

This is a complete and valid class declaration but notice that it does not contain a constructor declaration. If a constructor is called when a class instance is created, what is called when a StopLight instance is created? The answer is that the compiler is doing some of your work for you in this case. When you declare a class without any constructors, the compiler automatically generates a default constructor that takes no arguments and performs no operations. Consequently, the original StopLight declaration is equivalent to

 public class StopLight{   /* 0 -> Green      1 -> Yellow      2 -> Red    */   int greenYellowRed;   public StopLight(){   } } 

You should remember, however, that the compiler only generates a default constructor when no constructors are defined. If you declare a constructor, even one that takes one or more arguments, the default no-argument constructor will not exist unless you explicitly define it.

Troubleshooting Tip

If you have trouble accessing a no-argument constructor. See "No-Argument Constructor Not Found in Superclass," in the "Troubleshooting" section at the end of this chapter.


Construction Sequence

The construction of an object involves more than the execution of a single constructor. When an object is created, constructor calls are chained so that a constructor for each superclass of the object is also called. Constructors for the superclasses are executed first, so a subclass constructor can access superclass fields with the assurance that any initialization defined for them in their corresponding constructor has been performed. Before the constructor for a class is executed, any initialization statements found in its instance field declarations or instance initializer blocks are performed.

Assigning Default Values Using Multiple Constructors

Defining multiple constructors enables you to create an object in several different ways. As with regular methods, you can overload constructors by declaring multiple versions in which each accepts a different set of parameters. This practice is prevalent in the Java libraries themselves . As a result, you can create most data types (such as java.lang.String and java.net.Socket ) while specifying varying degrees and types of information.

If you make use of multiple constructors, try to reuse any common initialization code that you write. Because Java does not support variable parameter lists or default parameter values in method calls, multiple constructors that reuse common code are often implemented to address this need. One constructor can call another using the this keyword as long as it is done as the first statement in the method. For example, the following two constructors could be used to create class instances either with or without default parameter values:

 public Point() {   // no initial position specified, use default of (0,0)   this(0,0); } public Point(initialX, initially) {   x = initialX;   y = initially; } 
Implementing a Singleton Using a Private Constructor

The classic text on object-oriented design patterns ( Design Patterns, Erich Gamma et al, Addison-Wesley, 1995) introduced the Singleton pattern among many others. The purpose of this often-used pattern is to provide a common way to ensure that only one instance of a class exists in a program and that it is globally accessible. A Singleton is typically used for a class that encapsulates access to an external resource (for example, a relational database connection) in which the creation of multiple instances would be costly and possibly error prone. Listing 7.6 shows an approach for implementing a Singleton in Java.

Listing 7.6 DatabaseConnection.java ” A Singleton Class
 public class DatabaseConnection {   private static DatabaseConnection singleton;   private DatabaseConnection() {     // do steps to establish connection to database     ...   }   // only access to an instance of DatabaseConnection   public static DatabaseConnection getInstance() {     if ( singleton == null ) {       singleton = new DatabaseConnection();     }     return singleton;   } } 

The definition of DatabaseConnection ensures that the class is instantiated only once and that this instance is made accessible to all classes through the public getInstance() method. The getInstance() method also demonstrates lazy instantiation in that the Singleton instance is not created until it is needed.

Overriding Methods

Creating two methods within the same class that have both the same name and the same parameter list is illegal. It would be impossible for the compiler to associate a call with one method instead of the other. However, you have already seen an example of a subclass declaring a method that has the same signature as one in its superclass in the discussion of polymorphism. This reuse of a method signature is called overriding a method. For an example, start with the Elevator class shown in Listing 7.7.

Listing 7.7 Elevator.java ” A Simple Elevator Class
 class Elevator {   ...   private boolean running = true;   ...   public void shutDown() {     running = false;   } } 

At some point, you realize that this elevator just isn't very safe, so you decide to create a safer one. You want to extend the old Elevator class and maintain most of its properties, but change some of its behavior as well. Specifically, you want to check to make sure the elevator car is empty before stopping, so you override the shutDown() method as shown in Listing 7.8.

Listing 7.8 SaferElevator.java ” A Safer Elevator That Extends Elevator
 class SaferElevator extends Elevator {   ...   public void shutDown() {     if ( isEmpty() )       running = false;     else       printErrorMessage();     }  } 

Note that overriding is accomplished only if the new method has the same name and parameter list as the method in the parent class. If the parameter signature is not the same, the new method will overload the parent method, not override it. For example, look at Listing 7.9.

Listing 7.9 SaferElevator.java ” Safer Elevator with an Overloaded shutDown(),
 Not an Overridden One  class SaferElevator extends Elevator {   ...   public void shutDown(int delay) {     if ( isEmpty() )       running = false;     else       printErrorMessage();   }  } 

In this case, the shutDown method from the Elevator class is still used for instances of SaferElevator if a shutdown is requested without a specified delay. Adding the integer delay parameter to the method changes the method signature so it is not an override. The new shutDown method is still valid, however, and can be called, but it has merely overloaded the original shutDown, as you learned in Chapter 4.

Note

When you override a method, you can't change its name or parameter list but you do have some flexibility with the access specifier and the throws clause, if there is one. An overriding method can be more accessible than its parent (for example, a protected method can be overridden as public but not as private). Also, if a method declaration includes a throws clause, an overriding method can be implemented so that all exceptions are handled and no throws clause is needed or the listed exceptions are subclasses of those specified in the parent class.

These two options might seem confusing at first so look at the implications. The key here is that polymorphism is only possible if subclass instances can be treated as instances of a common parent class. If it were possible for a subclass to override a public method in a parent class as private, the compiler would accept a call to the method using a reference to the parent class. However, if this reference were to point to an instance of the subclass at run time, it would be impossible for the call to the private override of the method to take place. Now consider the declaration of thrown exceptions. A method is required to handle or throw any exceptions declared in the throws clause of each method it calls. If a subclass were to throw exceptions not declared as being thrown by the parent class, it would be impossible for a method that uses a reference to the parent class to know what exceptions to handle.


When you override a method, you might need to replace the behavior implemented in the superclass or you might only need to add to it. The super keyword allows you to do this by calling a superclass method from within a subclass. For example:

 public void reset() {   // reset instance fields   counter = 0;   ...   // reset superclass state   super.reset(); } 

The call to a superclass method can occur anywhere within a subclass method.

Note

Unlike C++, Java does not allow a specific superclass to be named as part of a method call. In Java, superclass calls are always made to the immediate parent class.


The super keyword also applies when you are defining a constructor for a subclass. Although calling a superclass constructor is not much different from calling any other method, its syntax might seem confusing at first:

 public CheckingAccount(String accountNum) {   super(accountNum);      // perform subclass initialization   ... } 

There are two points to take note of here:

  • A call to a superclass constructor must appear as the first statement in a subclass constructor if it is explicitly included.

  • If a subclass constructor does not explicitly call a superclass constructor, the compiler automatically inserts a call to the no-argument constructor of the superclass.

Caution

A common error in the use of superclass constructors occurs when a parent class has at least one constructor defined with one or more arguments and doesn't have a no- argument constructor declared. In this case, the compiler will not generate a no-argument constructor automatically. Therefore, all subclass constructors must explicitly call a superclass constructor because there is no default constructor for the compiler to use in an automatically generated call.


Using Methods to Provide Guarded Access

Although it might be preferable to restrict access to certain fields in your class, it is typically necessary to provide some form of access to those fields. Access to fields is regularly provided through methods that are less restricted than the fields. An example of this approach was shown previously in the Circle class of Listing 7.3. These access methods are often referred to as set and get methods.

Class Methods

Static methods are referred to as class methods. As in the case of class fields, the implication of this term is that static methods are associated with a class as a whole and not a particular instance. Class methods can access class fields but not instance fields without referring to an instance of a class.

   


Special Edition Using Java 2 Standard Edition
Special Edition Using Java 2, Standard Edition (Special Edition Using...)
ISBN: 0789724685
EAN: 2147483647
Year: 1999
Pages: 353

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net