Chapter 6

Creating Programs with Java

by Bryan Morgan


CONTENTS

Chapter 5 "Elements of the Java Language," introduced you to the syntax, requirements, and capabilities of the Java programming language. Java's syntax, combined with proper object-oriented design, allows programmers to build flexible, extensible systems. However, writing code in Java does not always result in good solutions. Although building procedural applications forces programmers to at least determine which variables and methods to use to reach some result, object-oriented applications require much more planning.

C++ veterans probably realize that it is possible to write a C++ program that is not object oriented. C programmers making the switch to C++ often fall into this trap. They create one or two extremely large objects to contain all of the application's GUI, logic, and database access layers. When the application is completed, none of its components can ever be reused by other programmers or projects. In addition, new C++ programmers often forget to define their operations and properties clearly. Therefore, any bug left in the software can be difficult to track down and correct. Likewise, correcting that bug often means changing identical lines of code dozens of times throughout multiple code modules. Doing a proper object design before the implementation can limit the severity of some of these problems. In addition, a proper design should result in a set of objects that can be reused in other applications.

A variety of language features in Java (discussed later in this chapter) help programmers create objects. Java also enforces object-oriented programming by requiring that every single line of code within an application must exist within an object (be it a class or an interface). C++ also makes use of a similar object type (also known as a class); however, C++ also borrows the C language convention that allows variables and methods to be declared "globally" outside of a class.

Although the designers of C++ undoubtedly had good reasons for adopting this technique, the end result is that C++ source code can be difficult to interpret. Although similar in syntax to C++, Java greatly streamlines the look and feel of source code by removing header files and by forcing all variables and methods to be declared within a class. To provide an even cleaner interface, each Java source file can contain only one publicly accessible class. This source file must have the same name as the public class within the file. This simple feature allows a developer to quickly identify the source file in which a particular class is defined.

The Goals of This Chapter

This chapter walks through the steps required to design a standalone Java package named Politics. The classes contained in this package are used to model elected officials within the American political system. The demonstration uses Java's object-oriented features to design objects in a flexible manner (the object-identification stage) so that virtually any type of politician can be "built" using these components (the object-construction stage). The politicians can be combined into a group (such as the Senate or House of Representatives), which can also be represented as an object. The demonstration also builds and runs several small applications that show these political objects hard at work (the application-assembly stage).

Object-Oriented Design

Object-oriented design is a superset of the object-oriented programming process. It deals with the "before" and "after" portion of the software-development process-an aspect of development that many development teams often ignore. Typical stages in the object-oriented design process include

Once the application is completed successfully, it will continue to be extended or modified as requirements continue to evolve. The success of your object design will become readily apparent at this time. One other "offshoot" of the design process is that many objects created during the application design and construction process can be reused within new applications. For example, suppose you construct a set of financial trading objects for use in an application for Company X. If you design and implement these object cleanly, you can reuse them weeks or months later when you start to write a similar application for Company Y. This illustrates the beauty of a good object design.

Thinking in Terms of Objects

Generally speaking, every application can be broken down into a core set of objects that are used repeatedly throughout the program. Many of these objects are supplied with Java (buttons, dialogs, threads, menus, and so on), and many other objects can be purchased from third-party developers (spreadsheets, charts, database queries, and so on). You, the developer, can also create objects in order to encapsulate a set of properties and methods within a data type. This data type, known as a class, can inherit from other existing classes and can possibly be reused later in other applications if it is generic enough.

Obviously, you cannot reuse all objects across multiple applications. For instance, classes created to encapsulate common geographical information system (GIS) operations will likely never be reused by corporate MIS programmers writing accounting applications. However, programmers who make the mistake of mixing GUI functionality with the internals of a non-GUI object have been known to create a GIS class that cannot be reused by other GIS applications! Listing 6.1 illustrates a Map class that does not lend itself to code reuse.


Listing 6.1. A poorly designed class.

class Map 

{

float scale;

float top_Lat;

float top_Long;

String Title;

String Units;

  

void DrawMap(MapDialog dialog)

  {

/* Add Drawing Code Here */

  }

}


Because it passes arguments to the DrawMap() method, this Map class can be drawn only on the surface of a MapDialog dialog box. Therefore, if you had another application that required some type of mapping, you would probably have to modify or rebuild this Map class before you could reuse it (chances are, the next application won't use the MapDialog class). Listing 6.2 shows a better way to build the Map class.


Listing 6.2. A correctly designed class.

class Map

{

float scale;

float top_Lat;

float top_Long;

String Title;

String Units;

}



class MapDialog

{

Map theMap;

... /* Provide other member variables and methods */

  ...

  ...



void DrawMap()

  {

/* Add Drawing Code Here That Uses theMap Member Variable */

  }

}


Notice that in Listing 6.2, the GUI is completely separate from the implementation of the Map class. Now this class can be reused in any application that requires some type of Map object, and it can be inherited from where needed.

A Brief Review of Object-Oriented Programming

The primary features of object-oriented programming were introduced in Chapter 3 "Object-Oriented Programming with Java." They are as follows:

Encapsulation is the process of grouping related properties and methods within a single object. If a class named Animal contains a property known as Species and a method named Run(), both of these attributes can be addressed as members of the Animal class:


String temp = Animal.Species;

if (BeingChased = true) 

{

Animal.Run();

}

Using encapsulation to group class members allows you to think of a data type as a true "object." The data type has a set of visible properties and actions that collectively give that object some behavior.

Inheritance allows the software developer to build objects that inherit the attributes of another class. These attributes can be overridden, where required, to give the child class a set of unique attributes that differentiate the child from the parent. The child can also have new attributes to give it capabilities that were nonexistent in the parent. To allow inheritance from another class, a Java class must use the extends keyword:


class Dog extends Animal;

class GermanShepherd extends Dog;

class SeeingEyeDog extends GermanShepherd;

Polymorphism means different things to different people. At its simplest, polymorphism allows an object to change the implementation of some attribute without modifying that attribute's definition within the program. For example, the Dog class can override the Animal class's Run() method without changing the method's definition.

The following code uses polymorphism to override the Animal class's Run() method:


Class Animal

{

void Run()

  {

return;

  } 

}



class Dog extends Animal

{

void Run()

  {

/* Provide implementation here */

  }

}

Declaring a class of type Dog and calling its Run() method will call the method defined in the Dog class (not the Run() method defined in the Animal class). In a procedural language, only one method could be named Run(). Any attempts to create another method with this name would result in a compile-time error.

Polymorphism also allows entire classes or interfaces to be cast in terms of their parent classes. For instance, the following code is perfectly valid in Java:


Dog Fido = new Dog();

Animal thing = Fido;

The Fido variable is of type Dog, but can be assigned to an Animal class because Dog derives from Animal. Calling the thing variable's Run() method will in turn call the Run() method that was defined in the Dog class.

These three primary features (encapsulation, inheritance, and polymorphism) allow the developer to build a complete application using existing and new objects based on a preliminary object design. This design process models the real-world objects that will be used by the application. It is necessary to model these objects first and use them as a basis for all other objects in the application (GUI, database, and so on).

The Object-Identification Stage

This section begins the object-identification stage mentioned earlier in the chapter. The purpose of this stage is to identify and outline the primary objects that will be modeled in Java code. This discussion uses the theme of American politics to illustrate the object-identification process.

This example assumes that every elected office is held by some type of politician. The definition of a politician is someone who campaigns for public support and who runs against other politicians in an election. The winner of the election is allowed to hold a public office for some amount of time. Each politician must have an opinion on a variety of issues (for example, environment, crime, economy, defense, social issues). Many politicians (no matter what their individual opinions are) can be grouped into a voting body to approve or disapprove of new laws. Because politicians seem to be involved in virtually every stage of politics, the first step is to design a Politician object that will be reused throughout the Politics package.

The Politician Object

When designing the Politician object, a number of properties immediately spring to mind:

All of these properties indeed describe a generic politician. Another possible property to add to the list might be Republican or Democrat. Because we're accustomed to thinking of politics in terms of these two parties, this option is tempting. However, throughout this country's history, many political parties have come and gone, and new parties are very likely to continue to emerge in the future. Therefore, hard-wiring the Politician object to one of these two parties limits its flexibility. A better technique is to build a generic Politician object and then derive the specific parties' politicians from the base Politician class. This method uses Java's inheritance capabilities and yields an extensible design.

In addition to a common set of properties, every politician also performs a few common actions while in elected office:

All these actions will be implemented as methods in the object-construction stage.

The Issues Objects

Now that you have identified the basic characteristics of a Politician and made fundamental design decisions (ignore party affiliation for now), it is time to think about the different issues that define a politician's voting tendencies. Some of the hot-button issues that always seem to dominate political discussions are crime, economics, religion, and international relations. Each of these issues can be broken down into separate sub-issues that each politician is either for or against. (This is necessary because, of course, all politicians are for crime control, a good economy, freedom of religion, and strong foreign policy. How each politician proposes to deal with each of these issues is another matter!) Examples of some of these topics include

Java provides two separate ways for the object designer to add features such as these to classes. The first option allows you to add all the related methods to a single class (such as our Politician class). The second option is to group all the related methods into an interface. If the methods are members of an interface, any class that chooses to do so can implement that interface. Because Java supports only single inheritance of classes but allows implementations of multiple interfaces, classes that choose to implement an interface gain functionality missing from their parent class. In addition, thanks to polymorphism, once the interface has been implemented, the class can then be type cast to an interface object.

As the example expands to actually build these objects, all of the "issues" methods will be grouped together into related interfaces. Although the base Politician class will not necessarily need to implement these interfaces, other children of Politician will be required to. The following section discusses the object-construction stage in detail.

The Object-Construction Stage

The previous section discussed the overall premise for the design of a set of objects related to politics. These objects will be grouped together within the Politics package once they are built. The purpose of this section is to construct the objects using what you know about the Java language and the Visual J++ development environment. Because classes are the building blocks of Java, the first step is to lay out some of the Politics classes.

Building Classes

To accurately model the political process, a large number of objects are required, many of which contain hundreds (or thousands) of members. At its simplest, though, the driving force behind all of the committees, parties, and lobbying organizations is the politician. For this example, the rest of the general public is placed into one of two possible categories: voters and activists. Voters are average citizens who have opinions on issues, but never feel the need to attempt to affect public policy outside the polls. Activists, meanwhile, are actively involved with some political issue and vigorously defend their position.

With these assumptions, three primary base classes should jump out: Politician, Activist, and Voter. Every individual in the political process can be derived from one of these three classes. The examples in this chapter focus on the Politician class and its corresponding responsibilities. Based on the previous discussion of a Politician object, Listing 6.3 provides a good start for the construction of a Politician class.


Listing 6.3. The Politician class.

package Politics;

/*

 *

 *  Politician Class

 *

 */

public abstract class Politician 

{

  private String Name;

  private int Age;

  private String Gender;

  private boolean Married;

  protected boolean GoodHair;

  protected int Personality; // on a scale of 1 to 10



  abstract public boolean Vote(String bill);



  public void KissBabies()

  {

    return;

  }



  public void setName(String newName)

  {

    Name = newName;

  }



 public void setAge(int newAge)

  {

    Age = newAge;

  }

  

 public void SetMaritalStatus(boolean newStatus)

  {

    Married = newStatus;

  }



  public String getName()

  {

    return Name;

  }



  public int getAge()

  {

    return Age;

  }



  public boolean GetMaritalStatus()

  {

    return Married;

  }

}


To create this class using Visual J++, do one of the following:

Notice that the Politician class was defined to be an abstract public class. This designation means that at least one method in the class was defined as an abstract method. Abstract methods are methods that are defined by a superclass, but carry no actual implementation. Any class that inherits from the superclass is required to provide an implementation for the method. In this first example, the Vote() method was declared to be abstract. The KissBabies() method was implemented within this class because, in effect, it carries very little weight or influence in the entire political process. (Any politician from any party can be seen in a picture with a baby and look good; therefore, no other classes will probably want to override this method.)

Data Hiding and Access Methods

Notice also that a set of helper methods was provided to give other classes access to the Politician's member variables. These methods are setName(), setAge(), SetMaritalStatus(), getName(), getAge(), and GetMaritalStatus(). Hiding data and providing these access methods is considered good object-oriented programming practice. It prevents child classes from inadvertently accessing or modifying class member variables. It also allows the programmer to perform other operations each time one of its member variables is set. For example, suppose that before getting a divorce, a politician wants to determine whether his public-opinion rating would be damaged in any way. Adding the following methods and variables to the class would track public opinion and perhaps allow the politician to get a divorce:


private boolean RatingsUp = true;

private double publicOpinion = 1.00;

.

.

.

protected void SetPublicOpinion(double newValue)

{

  if ((newValue <= 1.00) && (newValue >= 0.00))

  {

    publicOpinion = newValue;

    if (publicOpinion < newValue)

      RatingsUp = false;

    else

      RatingsUp = true;

  }

}



protected boolean GetDivorce()

{

  if (RatingsUp)

  {

    SetMaritalStatus(false);

    return true;

  }

  else

    return false;

}

Both the GetDivorce() and the SetPublicOpinion() methods perform double duties. They set internal class variables, and they also perform additional logical checks on the input data. If these variables (Married, RatingsUp, and publicOpinion) were all made public, any class that used the Politician class or inherited from it could modify these variables in any way. In short, always try to hide as much data as possible using the protected and private keywords within objects. This method allows the design to be extremely flexible down the line and may allow you to reuse large amounts of code without modification.

Using Hidden Helper Classes

As we are well aware, no politician acts completely alone. Instead, politicians are generally surrounded by campaign managers, policy advisers, assistants, and other aides. Because these support personnel exist primarily to support the politician, the next step is to implement a helper class within the POLITICIAN.JAVA source file. This class, named PoliticalAssistant, will be visible only to the Politician class. (Remember that only one public Java class can be declared per source file!) Adding a private class within a public class's source file will demonstrate an effective example of using hidden helper classes. The private PoliticalAssistant class models the real-world political process in that no one in the public is usually concerned about who a politician's advisers are or what they do. This assistant is instead most important to the politician alone. In general, any discussions with the assistant usually take place through the politician in the form of a news conference or an interview.

Listing 6.4 shows the PoliticalAssistant class and changes that were made to the Politician class.


Listing 6.4. The Politician and PoliticalAssistant classes.

package Politics;

/*

 *

 *  Politician Class - Uses PoliticalAssistants and public

 *  opinion to make "informed" decisions.

 *

 */

public abstract class Politician

{

  .

  .

  .

  private PoliticalAssistant[] assistants; 



  public Politician()

  {

    /* Hire some political assistants */

    assistants = new PoliticalAssistant[6]; 



    assistants[0] = new PoliticalAssistant("CRIME");

    assistants[1] = new PoliticalAssistant("ENVIRONMENT");

    assistants[2] = new PoliticalAssistant("ECONOMICS");

    assistants[3] = new PoliticalAssistant("SOCIALISSUES");

    assistants[4] = new PoliticalAssistant("EDUCATION");

    assistants[5] = new PoliticalAssistant("FOREIGNPOLICY");

  }

  

  public boolean MakeDecision(String Area, String Issue)

  {

    boolean returnValue = false;



    for (int i = 0; i <= 5; i++)

    {

      if (assistants[i].GetExpertise().equals(Area))

        returnValue = assistants[i].MakeDecision(Issue);

    }

    return returnValue;

  }

}



class PoliticalAssistant

{

  private String AreaOfExpertise;



  PoliticalAssistant(String Expertise)

  {

    AreaOfExpertise = Expertise;

  }



  public GetExpertise()

  {  

    return AreaOfExpertise;

  }



  public double MeasureRisk(String Issue)

  {

    /* Return a constant value for now!

   The actual implementation of this method might

   go out and query a database to determine the level

   of political support for some issue.  This value would

   range from 0.0 to 1.0 and would be returned to the 

   Politician. */

   return 0.5;

  }

}


Some interesting changes were made to the Politician class in Listing 6.4. A private array of PoliticalAssistant classes was added so that the politician could have someone to consult before making a decision. To create and initialize an array of PoliticalAssistants, a Politician constructor was added. This constructor initializes an array of assistants of constant size. Each one of these assistants is a specialist in a certain political area. The politician's opinion on an issue can be determined by calling the Politician.MakeDecision() method and indicating a specific issue. Note that this method was identified as a public method so that anyone (a voter, fellow politician, or lobbyist) can determine the politician's opinion on any issue at any time. (Maybe that's why they get paid the big bucks!)

Adding Other Classes to the Project

Listing 6.4 illustrates the addition of a class within the POLITICIAN.JAVA file. Building the POLITICIAN.JAVA source file using Visual J++ should have resulted in two class files being created on your drive: POLITICALASSISTANT.CLASS and POLITICIAN.CLASS.

Note
If you used the project workspace file supplied with the CD-ROM in this book, these class files will be located in the .\POLITICS folder. The files are output to this folder because these classes were declared to members of package Politics. If the first line of the POLITICS.JAVA source file were changed to package Politics.BaseClass, the files would have been output to the .\POLITICS\BASECLASS folder. Java converts the . between names in the import and package statements to the file system directory separator, which is \ in the case of Windows 95/NT. Visual J++ then utilizes the CLASSPATH environment variable to determine where (in which directories) to search for the package or imported classes.

Many programmers do not approve of the practice of passing String values around as parameters for examination. For instance, in Listing 6.3, the Vote() method was defined as


abstract public boolean Vote(String bill);

Passing a String value for the bill parameter probably will not allow the Politician class to make an informed choice based on its current capabilities (that is, Which bill? What is it for? When is the vote?).

The Legislation Class

Suppose now that a new class named Legislation is defined that contains a number of useful parameters including

If a class such as this existed, a politician could receive a Vote() request using an instantiated class of this type as a parameter. This type of information would enable the Politician class to make a more intelligent decision when voting. Listing 6.5 shows an initial implementation of the Legislation class.


Listing 6.5. The Legislation class.

package Politics;



import Politician;



/*

 *

 * Legislation

 *

 */

public final class Legislation 

{

  private String DateOfVote;

  private String PrimaryArea;

  private String PrimaryIssue;

  private String LegislationText;

  private Politician LegislationOwner;



  public Legislation(String Date, String Area, String Issue, String Text, 

    Politician Owner)

  {

    DateOfVote = Date;

    PrimaryArea = Area;

    PrimaryIssue = Issue;

    LegislationText = Text;

    LegislationOwner = Owner;

  }



  public String GetDateOfVote()

  {

    return DateOfVote;

  }



  public String GetPrimaryArea()

  {

    return PrimaryArea;

  }



  public String GetPrimaryIssue()

  {

    return PrimaryIssue;

  }



  public String GetLegislationText()

  {

    return LegislationText;

  }

}


Using the Legislation class, we can modify the Politician class's Vote() method to return an "intelligent" vote on a piece of legislation based on the legislation's issues (see Listing 6.6).


Listing 6.6. Modifying Politician to use the Legislation class when voting.

import Legislation;



public class Politician

{

  .

  .

  .  

  public boolean Vote(Legislation bill)

  {

    return MakeDecision(bill.GetPrimaryArea(), bill.GetPrimaryIssue());

  }

  . 

  .

  .

}


In Listing 6.6, the Vote() method was changed from an empty abstract method to an actual method within this class. The new Vote() method takes a Legislation object as an argument and, based on the Legislation's area and issue, returns a boolean true or false value.

Note
At first glance, you might think that some redundancy is occurring within the Politician class because the Vote() method simply issues a call to the MakeDecision() method. Why not just get rid of one of these methods?
The answer is that although a politician may rarely be required to vote on an issue, members of the media, staff, colleagues, and the general public will continually ask for his or her opinion. Therefore, separating the Vote() method from the MakeDecision() method allows the designer to extend the MakeDecision() method with additional capabilities without ever changing the Vote() method (or vice versa).

Now that the Politician and Legislation classes have been somewhat finalized, only one last "base" class remains before we can begin to extend the class library. The purpose of this class is to group related sets of politicians and legislation together. Because a group of politicians that passes laws is commonly known as a legislative body, the name of the final base class is LegislativeBody.

The LegislativeBody Class

As was the case during the design of Legislation and Politician, the primary goal in designing the LegislativeBody class should be to make it as generic as possible. Thinking back to the Politician class, notice that nothing in the class specifically ties it to a representative, mayor, or councilman. In fact, nothing even ties it directly to an American politician! (The Politician could be the prime minister of France...Politician doesn't care.) Therefore, LegislativeBody should be as generic as possible, yet implement as much functionality as possible. Listing 6.7 shows a simple LegislativeBody class that will be extended later in the chapter.


Listing 6.7. The LegislativeBody class.

package Politics;



import Politician;

import Legislation;



/*

 *

 * LegislativeBody - Used To Group Related Politicians Together

 *

 */

public class LegislativeBody 

{

  protected String Location;

  private Politician[] Members;



  // Return Location of Body (Washington, Richmond, Sacramento, etc.

  public String GetLocation()

  {

    return Location;

  }





  //Return number of politicians in body

  public int GetNumberOfMembers()

  {

    return Members.length; 

  }



  //Set Number of members in array of Politicians

  public boolean SetNumberOfMembers(int newNumber)

  {

    if (Members == null) 

    {

      Members = new Politician[newNumber];

      return true;

    }

    else

      return false;

  }



  //Add a politician to the LegislativeBody

  public boolean AddPolitician(Politician official)

  {

    boolean retValue = false;

    

    if (official != null)

    {

      for (int i = 1; i <= Members.length; i++)

      {

        if (Members[i - 1] == null)

        {

          Members[i - 1] = official;

          retValue = true;

        }

      } 

    }

    return retValue;

  }



  //Remove a politician from office

  public boolean RemovePolitician(Politician official)

  {

    boolean retValue = false;



    for (int i = 1; i <= Members.length; i++)

    {

      if (Members[i - 1].getName() == official.getName())

      {

        Members[i - 1] = null;

        retValue = true;

      }

    }

    return retValue;

  }



  /* Perform a vote on some piece of legislation */

  public boolean Vote(Legislation bill)

  {

    int Yeas = 0;

    int Nays = 0;

    boolean retValue;



    for (int i = 1; i <= Members.length; i++)

    {

      if (Members[i - 1] != null)

      {

        retValue = Members[i - 1].Vote(bill);

        if (retValue == true)

          Yeas++;

        else

          Nays++;

      }

    }



    if (Yeas >= Nays)

      return true;

    else

      return false;

  }

}


The LegislativeBody class makes extensive use of the existing Politician and Legislation classes. All legislative bodies are generally made up groups of politicians. The U.S. Senate has 100 members, for instance. Therefore, LegislativeBody contains an array of Politicians. The size of this array is set in the SetNumberOfMembers() method. Once the number of members in this legislative body has been set, you can use the AddPolitician() and RemovePolitician() methods to add or remove Politicians from this array. The Vote() method accepts a Legislation object as an argument and returns either a true or false based on the opinion of each politician. (Note that in this case, a tie wins.)

By this point, the design contains four separate classes that allow us to roughly model the political process. The remainder of the chapter focuses on inheriting from these classes to build more specific political classes (Congress or President, for instance). Listing 6.8 demonstrates the use of the classes that have been created thus far.

Note
Before entering and compiling this example, make sure that the source code for the Politician, PoliticalAssistant, Legislation, and LegislativeBody and class files are available. If you have chosen not to use the files located on the CD-ROM accompanying this book, create a new project named Listing8 and then create the class listed in Listing 6.8. In Visual J++ select the Build|Settings... menu item to select the output and class path directories. (Set the class path directory to the directory containing the Politics class files.) Because Listing8 is a standalone application and not a Java applet, select Stand-alone interpreter when Visual J++ asks how you would like to run this class.


Listing 6.8. Using the political classes.

/*

 *

 * Example8: Creates legislative body of five members

 *           and forces a vote.

 *

 */

import Politics.LegislativeBody;

import Politics.Legislation;

import Politics.Politician;



class Listing8 

{

  public static void main(String args[])

  {

    LegislativeBody CityCouncil = new LegislativeBody();

    CityCouncil.SetNumberOfMembers(5);



    Politician politico1 = new Politician();

    Politician politico2 = new Politician();

    Politician politico3 = new Politician();

    Politician politico4 = new Politician();

    Politician politico5 = new Politician();



    System.out.println("Adding politician...\n");



    CityCouncil.AddPolitician(politico1);

    CityCouncil.AddPolitician(politico2);

    CityCouncil.AddPolitician(politico3);

    CityCouncil.AddPolitician(politico4);

    CityCouncil.AddPolitician(politico5);

 

    System.out.println("Number of politicians = " + 

    CityCouncil.GetNumberOfMembers() + "\n");



    Legislation bill = new Legislation("Today", "CRIME", "PRISONS", 

      "BUILD MORE", politico1);

    System.out.println("Date of vote: " + bill.GetDateOfVote() + "\n");

    System.out.println("Area:  " + bill.GetPrimaryArea() + "\n");

    System.out.println("Issue: " + bill.GetPrimaryIssue() + "\n");



    boolean retValue = CityCouncil.Vote(bill);



    System.out.println("The result of the vote was: " + retValue + "\n");

  }

}


The Listing8 program initially creates a new LegislativeBody class named CityCouncil. Five Politician objects are added to the CityCouncil class, and a vote is taken on whether to build more prisons. Because the PoliticianAssistant class is hard-wired at this point to always return false, the output of the Vote() method is false. When this class is run in Visual J++, the following output should be displayed:


Adding politician...



Number of politicians = 5



Date of vote: TODAY



Area: CRIME



Issue: PRISONS



The result of the vote was:  false

One way to make these classes a little more useful is to replace the contents of the PoliticalAssistant.MeasureRisk() method with a database query (or a request for user input). At this point, however, the objects that have been created do a good job of showing basic object-oriented design and development.

Using Inheritance

The classes created thus far are sufficient to write and run a basic program, as shown in Listing 6.8. This section explains how to use the object-oriented programming feature known as inheritance to create new classes that extend the existing classes so that they more accurately model real-world political environments.

Recall that Java uses the extends keyword to inherit from a superclass. Superclasses are also commonly called parent classes. A superclass that has children but inherits from nothing else can also be referred to as a base class. Examples of base classes are the LegislativeBody, Legislation, and Politician classes created earlier in this chapter. The LegislativeBody and Politician classes will be extended to more accurately model the American political system.

Inheriting from Politician

The Politician class was originally created to model the typical attributes and duties of a politician. A politician also has the following features:

One basic premise of the design was that all politicians, no matter who they are or where they reside, share this basic feature set. This broad generalization works fine for this example.

However, depending on the type of politician, this set of variables and methods may not allow the politician to perform his or her job completely. For instance, the President of the United States must meet with foreign leaders, converse with members of Congress, attend sporting events, and speak in public regularly. A senator must travel often to visit constituents from the home district, meet with special interest groups, and attend committee meetings. Therefore, in order to provide greater flexibility to the builder of political software applications, new classes must be inherited from Politician. Two new classes are be created here: President and Senator. These classes will inherit from Politician. Both of these classes will add new capabilities that are not found in the Politician class. Listing 6.9 creates a President class that inherits from the existing Politician class.


Listing 6.9. The President class.

package Politics;



import Politician;



/*

 *

 * President

 *

 */

public class President extends Politician

{

  public void MeetWithForeignLeader(Politician leader)

  {

    /*

      Add code to hold meeting with dignitary.

    */

    return;

  }



  public void TalkWithCongressman(Politician congressman)

  {

    /* 

      Add code to hold meeting with U.S. Congressman

    */

    return;

  }



  public void AttendEvent(String location)

  {

    /*

      Add code to travel to, prepare, and attend an event

    */

    GiveSpeech();

    return;

  }



  public void GiveSpeech()

  {

    /* 

      Give speech based on some topic

    */

    return;

  }

}


Listing 6.10 creates a class designed to simulate a U.S. senator. The Senator class extends the Politician class.


Listing 6.10. The Senator class.

package Politics;



import Politician;



/*

 *

 * Senator

 *

 */

public class Senator extends Politician

{

  public String HomeState;

  public int District;

  public String Committee;



  public void TravelToHome()

  {

    /* 

      Go to home district and meet with people

    */

    return;

  }



  public void MeetWithGroup(String SpecialInterest)

  {

    /*

      Meet with members of a special interest group

    */

    return;

  }



  public void AttendCommitteeMeeting()

  {

    /* 

      Go to committee meeting, listen, and vote if necessary

    */

    return;

  }

}


With the creation of these two classes, the Politician class has been successfully reused. Although the implementations of the Senator and President classes appear to contain only a few variables and methods, in reality Senator and President have access to all public and protected members of the parent Politician class. The following statements are possible because of inheritance:


President AbeLincoln = new President();

AbeLincoln.SetPublicOpinion(0.85);

AbeLincoln.GiveSpeech();

boolean MaritalStatus = AbeLincoln.GetMaritalStatus();



Senator BobDole = new Senator();

BobDole.SetName("Bob Dole");

BobDole.AttendCommitteeMeeting();

boolean answer = Vote(bill);

In addition to the Politician class, one other base class-the LegislativeBody class-is an excellent candidate for inheritance. Like Politician, LegislativeBody does a good job of roughly modeling a group of politicians that meet regularly to vote on various pieces of legislation. However, it was given only generic capabilities to provide maximum reusability.

Inheriting from LegislativeBody

Because the President and Senator classes have already been constructed, the next step is to build two legislative bodies to "hold" the offices of the President and Senators. These classes are the OfficeOfThePresident and Senate classes, shown in Listings 6.11 and 6.12.


Listing 6.11. The OfficeOfThePresident class.

package Politics;



import LegislativeBody;



/*

 *

 * OfficeOfThePresident

 *

 */

public class OfficeOfThePresident extends LegislativeBody

{

  private Politician VicePresident;



  public OfficeOfThePresident()

  {

    Location = "Washington, D.C.";

    SetNumberOfMembers(1);

  }



  public Politician GetVicePresident()

  {

    return VicePresident;

  }



  public void SetVicePresident(Politician veep)

  {

    if (veep != null)

      VicePresident = veep;

  }

}


Listing 6.12 creates a class designed to simulate the U.S. Senate. This class contains a group of senators (represented by the Senator class).


Listing 6.12. The Senate class.

package Politics;



import LegislativeBody;



/*

 *

 * Senate

 *

 */

public class Senate extends LegislativeBody

{

  private int NumberAdded = 0;

  private Politician CrimeCommittee[];

  private Politician EconomicsCommittee[];

  private Politician EnvironmentCommittee[];

  private Politician SocialIssuesCommittee[];

  private Politician EducationCommittee[];



  public Senate()

  {

    Location = "Washington, D.C.";

    SetNumberOfMembers(100);

    CrimeCommittee = new Politician[20];

    EconomicsCommittee = new Politician[20];

    EnvironmentCommittee = new Politician[20];

    SocialIssuesCommittee = new Politician[20];

    EducationCommittee = new Politician[20];

  }



  /* Randomly assign politicians to a committee */

  public boolean AddPolitician(Politician official)

  {

    NumberAdded++;

    int number = NumberAdded / 5;

    switch (NumberAdded % 5)

    {

      case (0):

        CrimeCommittee[number] = official;

        break;

      case (1):

        EconomicsCommittee[number] = official;

        break;

      case (2):

        EnvironmentCommittee[number] = official;

        break;

      case (3):

        SocialIssuesCommittee[number] = official;

        break;

      case (4):

        EducationCommittee[number] = official;

        break;

    }

    return super.AddPolitician(official);

  }

}


Inheritance allows the Java developer to continually extend and shape classes to meet the needs of the task at hand. Thus far, inheritance and encapsulation have been used extensively to build what is getting to be a large group of classes. Although you may have not realized it, the Senate class also used the object-oriented programming concept of polymorphism to enhance itself.

Using Polymorphism

By overriding the LegislativeBody.AddPolitician() method, the Senate class reused the name of a method in the subclass while changing its behavior. Now, in addition to adding an elected politician to the list of politicians within the LegislativeBody, Senate will also randomly add a politician to a Committee. Polymorphism, in this instance, allows the functionality of the AddPolitician() method to stay roughly the same and gives it added behavior. Polymorphism can be used when calling AddPolitician() as well. Note that this method accepts a Politician variable as an argument. Using polymorphism, this variable could actually be a Politician object or an object of any class that inherits from Politician (such as Senator or President). Listing 6.13 shows this use of polymorphism.


Listing 6.13. Adding Senators to the Senate using polymorphism.

/*

 *

 * Example13: Creates Senate of five members

 *

and forces a vote.

 *

 */

import Politics.Senate;

import Politics.Legislation;

import Politics.Senator;



class Example13 

{

  public static void main(String args[])

  {

    Senate USSenate = new Senate();



    //Add senators and set names

    Senator BobDole = new Senator();

    BobDole.setName("Bob Dole");

    Senator StromThurmond = new Senator();

    StromThurmond.setName("Strom Thurmond");

    Senator ConnieMack = new Senator();

    ConnieMack.setName("Connie Mack");

    Senator DianneFeinstein = new Senator();

    DianneFeinstein.setName("Dianne Feinstein");

    Senator ChuckRobb = new Senator();

    ChuckRobb.setName("Chuck Robb");



    System.out.println("Adding senators...\n");

    USSenate.AddPolitician(BobDole);

    USSenate.AddPolitician(StromThurmond);

    USSenate.AddPolitician(ConnieMack);

    USSenate.AddPolitician(DianneFeinstein);

    USSenate.AddPolitician(ChuckRobb);

    System.out.println("Number of senators = " + 

    USSenate.GetNumberOfMembers() + "\n");



    Legislation bill = new Legislation("Today", "CRIME", "PRISONS", 

      "BUILD MORE", ConnieMack);

    System.out.println("Date of vote: " + bill.GetDateOfVote() + "\n");

    System.out.println("Area:  " + bill.GetPrimaryArea() + "\n");

    System.out.println("Issue: " + bill.GetPrimaryIssue() + "\n");

    boolean retValue = USSenate.Vote(bill);

    System.out.println("The result of the vote was: " + retValue + "\n");

    System.out.println("Senator 1 = " + BobDole.getName());

    System.out.println("Senator 2 = " + StromThurmond.getName());

    System.out.println("Senator 3 = " + ConnieMack.getName());

    System.out.println("Senator 4 = " + DianneFeinstein.getName());

    System.out.println("Senator 5 = " + ChuckRobb.getName());

  }

}


In Listing 6.13, note that although AddPolitician() accepts Politician objects as a parameter, we are able to pass it Senate objects instead because Senate inherits directly from Politician. Therefore, every public member of Politician is available to the AddPolitician() method through the Senator objects.

Compiling and running this class should result in the following output:


Adding senators...



Number of senators = 5



Date of vote: TODAY



Area: CRIME



Issue: PRISONS



The result of the vote was:  false



Senator 1 = Bob Dole

Senator 2 = Strom Thurmond

Senator 3 = Connie Mack

Senator 4 = Dianne Feinstein

Senator 5 = Chuck Robb

At this point, an entire of package of reusable objects has been built using the object-oriented concepts of encapsulation, inheritance, and polymorphism. Each of these objects has a quantifiable set of properties and methods that specifically pertain to that object. The access keywords public, protected, and private were used throughout to control access to member variables and methods where needed.

This discussion concludes by demonstrating the use of one last feature of the Java language-the Java interface-to extend the Politics package. An interface is a grouping of public abstract methods that separates the design of an object from its implementation.

Adding Interfaces

An effective use of interfaces in the Politics package is to represent a politician's views on a variety of issues. The interfaces themselves comprise a set of public abstract methods and/or public static final variables. Defining the interfaces allows a related grouping of functionality to be self-contained in one unit. Any class can choose to implement an interface as it sees fit. (Recall that if a class implements an interface, it must implement all of that interface's methods!) To continue the Politics example, interfaces will be created to group together related sets of issues such as economics, education, social issues, and so on. A Politician class can choose to implement any interface as it is needed. Obviously, some issues (such as economics or crime) apply to every politician at every level. Other issues (such as local construction projects or school board decisions) apply only to specific politicians in specific locations. Continuing with the design decisions made earlier, interfaces that apply to all politicians are implemented within the Politician class.

The following sample interfaces could be implemented by the Politician class if so desired:


public interface Crime 

{

  public abstract boolean BuildMorePrisons();

  public abstract boolean EducateOffenders();

  public abstract boolean ShowZeroTolerance();

  public abstract boolean ForDeathPenalty();

  public abstract boolean ToughOnDrugs();

  public abstract boolean ForGunControl();

}



public interface Economics 

{

  public abstract boolean IncreaseDeficit();

  public abstract boolean TaxAndSpend();

  public abstract boolean SupplySider();

  public abstract boolean CutCapitalGains();

  public abstract boolean HasVotedToIncreaseTaxes();

}

public interface Education 

{

  public abstract boolean SpendMoreOnSchools();

  public abstract boolean PayTeachersMore();

  public abstract boolean EducationOverDefense();

  public abstract boolean SetHigherStandards();

  public abstract boolean SupportSchoolChoice();

}

Once again, the idea behind interfaces is to separate the design from the implementation of objects. The previous three interfaces (Education, Crime, and Economics) simply specify which methods will be implemented by classes that choose to do so. Keep in mind that Java's polymorphic capabilities allow programmers to type cast classes to the interfaces they implement. Therefore, the following statements are perfectly legal in Java:


class Politician implements Crime, Economics, Education

{

  ...

}



Politician politico = new Politician();

Crime crimeMethods = politico;

The politico variable is created as type Politician. However, once created, it can be cast to a Crime interface (just as Senator can be cast to a Politician or as OfficeOfThePresident can be cast to a LegislativeBody). Because Politician in this example implements the Crime interface, all methods in Crime are guaranteed to be in the Politician class.

One final example illustrates how effectively interfaces can be used within an application. Suppose the National Teacher's Union (NTU) is trying to determine the views of each individual politician in order to see that the union's views are represented in an upcoming vote. The NTU (a fictional union) class defines a method named DetermineOpinion() that will be used to determine whether an elected official is friendly toward educational issues. This method could be implemented as follows:


public boolean DetermineOpinion(Education opinions)

{

  int tally = 0;



  if (opinions.SpendMoreOnSchools()) then

    tally++;

  if (opinions.PayTeachersMore()) then

    tally++;

  if (opinions.EducationOverDefense()) then

    tally++;

  if (opinions.SetHigherStandards()) then

    tally++;

  if (opinions.SupportSchoolChoice() == false) then

    tally++;



  if (tally >= 3) then

    return true;

  else

    return false;

}

The DetermineOpinion() method accepts an Education interface as its argument, which allows this method to be completely flexible. We could call this method in a loop and pass in each member of the Senate to determine his or her opinions (assuming that the Senator class implemented this interface). However, it is just as possible to pass in each member of the general public (all 300-odd million of them!) and determine their opinions on a matter.

Summary

Object-oriented programming should always be preceded by a good object-oriented design. Stopping to consider the problem at hand nearly always results in a more reusable, more extensible set of objects than does programming in an ad hoc fashion. Java programmers have the luxury of an extremely large built-in class library that is part of the java package. Visual J++ programmers have additional capabilities in the Microsoft com package. Any Java programmer can extend all the public classes in these packages.

This chapter demonstrates the concepts of encapsulation, inheritance, and polymorphism by constructing a fairly sophisticated package named Politics. Grouping classes into packages allows these classes themselves to be viewed as a type of object. Any user seeing that a class is included in the Politics package will immediately know that the class has something to do with Politics. All classes in the Politics package can be imported by issuing the following statement:


import Politics.*;

The Java CLASSPATH environment variable controls where the compiler and Java Virtual Machine "look" for classes. As a Visual J++ developer, you have several options when setting the path to classes used in the application. You can set this class path for the specific project workspace by selecting the Build | Settings menu item and then selecting the General tab. You can also set the class path by modifying the CLASSPATH environment variable in AUTOEXEC.BAT (for Windows 95) or the system environment variables (for Windows NT). Visual J++ will also look in the Windows Registry under the MYComputer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Java_VM\Classpath Registry key. Modifying the class path using any of these techniques allows the compiler to find class files being imported.