HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

"Hi Everybody," John Tabbone announces as he walks into a class full of aspiring Java students. "Today, we are starting a multi-part class on object-orientation, OO for short." The students lean forward as if they were engaged in a campfire story. "I have heard the term before; John said it is central to Java programming," thinks one typical student. "I read somewhere that OO will probably be the dominant programming style until the end of the millennium," thinks the first student's typical classmate.

Object Orientation is a way of thinking. It is a tool used to model a system and, in our case, use that model to create a Java program. Many of the OO terms I will use were coined by Grady Booch of Rational Software Inc. For a more detailed examination of OO, you should read his book, Object-Oriented Analysis and Design with examples.

The first step in using OO is to realize that you are not writing a structured program as you might have done in languages like basic or c. I like to think of structured programming as the cookbook approach to development. You have some input (i.e., eggs, flour, milk, sugar), you follow a series of steps in a certain order (mix the eggs, milk and flour, add the sugar, stir, etc.) and you get an output (i.e., a cake). Structured programming is quite similar. You have some input (data), you follow a sequence of steps (your program) and you get an output (some modified data or desired result). The emphasis in structured programming is clearly on the sequence of steps one takes to turn input into output.

In OO, the fundamental thrust is modeling a system. A system is composed of participants and the interactions between those participants. For example, you might leave class tonight and go to your favorite video rental store to rent a new film. You will walk into the store, look at all of the tapes on the new releases wall and select one (or more than one). You will then go to the checkout counter, where you will give your membership card to a clerk. The clerk will check your id number against a database and perhaps tell you that you owe money, or just enter your video selection. You will pay, the clerk will give you your movie and you will leave.

This video store example is a system. Some of the participants are you, the clerk, a bunch of video tapes, a database of members, etc. What are the interactions between the participants? you select a video tape. The clerk checks the data base. You pay the clerk, etc.

So how does this turn into a program? Well, we need to model our participants in more detail. Grady Booch has very elegantly identified exactly what it is we want to model. We need to describe a participant's states, identity and behaviors. Let's look at our video store example with this in mind.

One of the participants in our system is you. What are your possible states in this system? You could have made a video selection, or perhaps not yet. You may owe money. You like new releases, or maybe you like science fiction. How about behaviors? You can make a selection. You can present your id card. you can pay. And identity? What is your identity? When asking yourself this question, you should really be asking "what kind of thing is this participant?".You are a person; however, person alone is not enough to distinguish you from other participants in the system (i.e., the clerk, who is also a person). You are a specific kind of person. You are a customer.

Let's look at another example. I commonly break out a chess board and pieces whenever I teach OO. If you don't know how to play chess, don't panic. We just want to do the following:

  • View Chess as a system
  • Identify the participants
  • Model their states, identities and behaviors
Step 1: View chess as a system
Chess is a game played by two players on an 8X8 board whose squares alternate in color. Each player has 16 pieces that may be either all black or all white. There are six kinds of chess pieces: 1 king, 1 queen, 2 bishops, 2 knights, 2 castles and 8 pawns. Chess is a turn-based game where each player can move a piece a certain number of squares in a certain pattern depending on the specific piece. A player may capture an opposing player's piece by legally moving onto the square occupied by the opposing piece. If the king is in jeopardy of being captured, we can say that the king is in check. If the king is in check, he must move or somehow situate other pieces so that he is no longer in check. The goal of the game is to force the opposing king into checkmate. This is done by positioning pieces in such a way that the opposing king cannot get out of check.

Step 2: Identify the participants
Who are the participants of this system? What objects do we intend to model? When flushing out objects, a common trick is to underline all the nouns in the system description. When we do so and aggregate all of the common objects (i.e., 64 pieces instead of 1 King, 1 Queen...), we have:

  • 2 players
  • 1 board
  • 64 squares
  • 32 pieces
  • Game logic (i.e., turns, perhaps there is a time limit per move )

Step 3: Model the states, identities and behaviors
Let's start with the pieces, the pawn in particular. A seasoned OO developer will notice that we are making a mistake here, but for those less experienced, just press on. A very important OO principle will emerge from our error.

What states can a pawn have? It has a color, a position, is it dead or alive? Is it in jeopardy of being captured by another hostile piece? A pawn has an owner (a Player) How about behaviors? A pawn can move, a pawn can capture and a pawn can die. Pretty straightforward.

What about identity? There are 16 pawns per game. The difference between any two pawns is not an identity difference and not a behavior difference, but a state difference. That is to say that a pawn is a pawn. Any two should be identified as pawns, regardless of which team they belong to or their position on the board. Any two pawns will also have the same behaviors (they move according to the same rules, they capture the same way). We can say that the difference between any two pawns is really a state difference. They might have different colors or different positions or different owners. Object-oriented languages provide us with a mechanism to describe these general models - a class. Using a class, we can create one model of a generic pawn that expresses all of the possible states and behaviors of any pawn. Once we have a pawn class, we can create as many pawn objects as we need. Think of a class as a blueprint. With a blueprint for a house you can build several houses (several house objects). Each house object can have a different color or different appliances (different states). The blueprint (class) will only indicate that there is a spot for appliances in the kitchen, or the walls can have a color. The blueprint describes the possible states; each object maintains its own particular state. In OO vocabulary, we would say that a pawn class has 16 instances.

Actually putting the model on paper in Java is a fairly straightforward process (see Listing 1). Once the class is created, we can create an instance of the class by declaring a variable of type pawn and calling new on it. So in some other part of the program, perhaps in our Player class, we might have code that looks like Listing 2. Notice how we create our Pawn class once and we can create several instances of it. Remember, the class declaration is only the blueprint. The instances are the actual objects that will maintain distinct states (positions, colors, life status, etc.).

Once the Pawn class is created, we should move on to the other pieces. Let's model a Queen. Answer these questions to yourself: What are the possible states of a queen? How about behaviors? Really try to answer them and read on only after you have thought about it.

Interestingly, a Queen and a Pawn have the same behaviors and states. As a matter of fact, If you model a Castle or a Bishop or any piece, you will find that they have the same behaviors and states. Only the identities are different. This is an Important part of OO: finding commonalities of objects. So, since we have done the work of modeling one piece (the Pawn class), we can make a few minor changes and have our one class represent any piece. Namely, we have to change the name of our class from class Pawn to class Piece. Our Player class will change too. Take a peek at Listing 3.

Once we recognize that all pieces are basically the same, we have to ask ourselves the question: What makes pieces different from one another? If you think about it, the primary difference is that pieces have different legal moves. A Pawn and a Knight move differently. You will notice that I have included a legal move behavior in the sample code but commented it out. We need to know a little more about OO in order to be able to make a decision as to whether we should include this method. We have to make a design decision.

Who among the participants of this system knows which moves are legal for a particular piece and which are not? Does each piece know? A player? The board? The game logic? Keep in mind that we are modeling a system, and the system is a real world system. In a real chess game, the players know which moves are legal because the players know the rules. A good OO model of chess should reflect this relationship. If you were to write this program, you should defiantly make legal moves part of the game logic (and keep in mind that a Player will know the game logic ) section of the program and not the individual pieces. It is a wise rule of thumb to keep the OO model as close to the real world model as possible.

However, in our case chess is an example. We are using it to illustrate some key points about OO. For our purposes, let's make each piece smart enough to know whether a particular move is legal or not. In other words, each piece will have a behavior that can determine whether a particular move is legal for that piece. A pawn will know if a move is legal for a pawn, a queen will know whether a move is legal for a queen, and so on.

How do we do this? If we add the logic needed to determine whether a Pawn's move is legal to class Piece, will we have to create new classes for Queen, King, Castle, etc. and redo all the work we have put into our piece class? We will have to rewrite all the other behaviors (i.e. setColor, getColor, etc.) and all the other states. Wouldn't it be great if we could build on class Piece and add some new behaviors or states? Well, we can. OO provides us with a mechanism known as inheritance. Inheritance allows one class to assume the states, identities and behaviors of another class. We already have a class Piece, which will be our base class or parent class. The goal is to create new classes, such as class Queen and class King, that add the logic specific to those pieces that can determine if a move is legal.

We will define the legalMove method in class Piece as being abstract. This means that we will not provide an implementation for the method in this class, only the behavior declaration (i.e., public boolean legalMove(Position p)). Furthermore, abstract means that we can not create an instance of class Piece, and any class that inherits class Piece must provide a method body (provide logic for), the moveTo method. Look at Listing 4 for some code examples.

In Listing 4, we have created a Queen class and a King class that extend (inherit from) the abstract base class Piece. Because a King and a Queen extend piece, they still have the same behaviors and states as a Piece. That is, a King can still setColor or moveTo. Same for the Queen. There are only two differences:

  1. The King and Queen class implement their own legalMove methods with logic specific for that piece.
  2. Instances of the King and Queen class can be identified as a Piece.
Remember, that first line of the class declaration indicates the identity(s) of the class. Whenever we use inheritance and the extends keyword, we put more than one identity on that line.

"That is it for today, class," says John. "Your assignment is to consider the following: All animals have some common behaviors. Animals have to eat, breath, drink, sleep, etc. However, the way particular animals actually do these things differs greatly. For example, both a human and a dog can run, but they do it in a completely different way. Think about how you would model some different animals in Java. You might have a base class Mammal that defines some common behaviors, and classes such as Human and Canine would implement specific behaviors. Try demonstrating this concept on paper. Afterwards, think of some other systems where inheritance might come into play."

"More Homework?" one student grumbles to another. "Yeah, but John doesn't want us to submit this one to him. He says he was swamped with e-mail from the last class." "So why bother doing it?" "Because we will probably need some practice before the next class and besides, we can always e-mail questions to him. He just doesn't have a TA to grade the assignments."

About the Author
John V. Tabbone is a lecturer at New York University's Information Technologies Institute, where he teaches two Java programming courses and advises on curriculum development. He has been a professional Java programmer since early 1996 and continues to consult on and develop systems for a variety of New York-based businesses. You may e-mail him with questions and comments at [email protected]

	

Listing 1. class Pawn 

// This line expresses the classes identity 
{ 
   protected Color      the_color;      // These lines express the possible 
states 
   protected Position   the_position; 
   protected boolean      is_captured; 
   protected boolean      in_jeopardy; 
   protected Player      the_owner; 

// These are the behaviors of a pawn.  
   public void setColor( Color c )         // You can set the color of a pawn 
   { 
      the_color = c; 
   } 
   public Color getColor()            // you can get the color of a pawn 
   { 
      return the_color; 
   } 

/* 
   Notice that this method is commented out. We donít know yet if a Pawn is 
smart enough to recognize whether a move is legal or not. 
   public boolean isLegalMove( Position p );      // A pawn will know if a move 
to a new  
   {                  // position is legal or not. 
      if ( this is a legal move for a pawn ) 
         return true; 
      else 
         return false; 
   } 
*/ 
   public void moveTo( Position p );         // A pawn can be moved to a new 
position 
   { 
      the_position = p; 
   } 
   public Position getPosition()         // A pawn can report its position 
   { 
      return the_position; 
   } 
   public void setCaptured ( boolean freedom_state )   // A pawn can be captured 
or somtimes freed 
   { 
      is_captured = freedom_state; 
   } 
   public boolean getCaptured()         // A pawn can report whether it is 
captured 
   { 
      return freedom_state; 
   } 
   public void setJeopardy( boolean jeopardy_state )   // A pawn can be alerted 
when it is in  
   {                  // Jeopardy 
      in_jeopardy = jeopardy_state; 
   } 
   public void getInJeopardy()         // A pawn can report whether it is in  
   {                  // Jeopardy 
      return in_jeopardy; 
   } 

   public void setOwner( Player p ) 
   { 
      the_owner = p; 
   } 

   public Player getOwner() 
   { 
      return the_owner; 
   } 
}  

Listing 2. class Player 

{ 
   ...               /**   Some state variable decleration 
   ...                  Some state variable decleration 
   ...                  Some state variable decleration 
                  **/ 
   protected Pawn pawn1;         // our pawn1 state-variable. pawn1 is a 
variable of  
                  // type Pawn 
   protected Pawn pawn2;         // our pawn state-variable pawn1 is a variable 
of  
                  // type Pawn 
  

/** This is an arbitrary method declaration. The purpose is to demnonstrate the 
use of new public void foo() 

   { 
      pawn1 = new Pawn();      // Here, an instance of class Pawn is created. 
      pawn2 = new Pawn();      // Here, another instance of class Pawn is 
created. 
   } 

Listing 3. class Piece 

  // This line reflects the new identity of our class 
 // The states and behaviors remain the same. 
{ 
   protected Color      the_color;      // States 
   protected Position   the_position; 
   protected boolean      is_captured; 
   protected boolean      in_jeopardy; 
   protected Player      the_owner; 

                     // These are the behaviors of a pawn.  
   public void setColor( Color c )         // You can set the color of a pawn 
   { 
      the_color = c; 
   } 
   public Color getColor()            // you can get the color of a pawn 
   { 
      return the_color; 
   } 
/* 
   Notice that this method is commented out. We donít know yet if a Pawn is 
smart enough to recognize whether a move is legal or not. 
   public boolean isLegalMove( Position p );      // A pawn will know if a move 
to a new  
   {                  // position is legal or not. 
      if ( this is a legal move for a pawn ) 
         return true; 
      else 
         return false; 
   } 
*/ 
   public void moveTo( Position p );         // A pawn can be moved to a new 
position 
   { 
      the_position = p; 
   } 
... 
... 
... 
}  

Listing 4. class Player 

{ 
   ...               /**   Some state variable decleration 
   ...                  Some state variable decleration 
   ...                  Some state variable decleration 
                  **/ 

/** 
   Here are the players pieces. Note that these should really be in an array, 
but for the purpose of this 
   exercise, this is fine. 
   protected Piece   pawn1; 
   protected Piece   pawn2; 
   ... 
   ... 
   protected Piece   pawn7; 
   protected Piece   pawn8; 
   protected Piece   queen; 
   protected Piece   king; 
   protected Piece   knight1; 
   protected Piece   knight2; 
   ... and so on for every piece. 
  

   /** This is an arbitrary method decleration. The purpose is to demnonstrate 
the use of new 
   public void foo()  
   { 
      pawn1 = new Piece();      // Here, an instance of class Piece is created. 
      pawn2 = new Piece();      // Here, another instance of class Piece is 
created. 
      ... 
      ... 
      pawn7 = new Piece();  
      pawn8 = new Piece();      // and we create instances of all of our 
pieces. 

      king = new Piece(); 
      queen = new Piece(); 
      knight1 = new Knight(); 
      ... and so on, new instances are created for each Piece decleration. 

   } 

Listing 5. abstract class Piece 

            // class Piece must be declared abstract because 
of  
                  // method legalMove 
                  // The states and behaviors remain the same. 
{ 
   protected Color      the_color;      // States 
   protected Position   the_position; 
   protected boolean      is_captured; 
   protected boolean      in_jeopardy; 
   protected Player      the_owner; 

                     // These are the behaviors of a pawn.  
   public void setColor( Color c )// You can set the color of a pawn 
   { 
      the_color = c; 
   } 
   public Color getColor()// you can get the color of a pawn 
   { 
      return the_color; 
   } 
/* 
   We do not provide an implementation for this method, only the declaration. 
The method is  
   declared abstract to indicate that classes who inheret from this class will 
have to provide the  
   implementation. 
*/ 
   abstract public boolean isLegalMove( Position p ); 

   ... 
   ... 
   ... 
} 

/** 
The Queen class inherits most of the behaviors and states from class Piece, it 
must only 
provide the specific logic necessary to determine whether a move is legal for a 
Queen. 
**/ 
class Queen extends Piece 
{ 
   public boolean isLegalMove( Position p ) 
   { 
// Insert Queens legal move logic here!! 
   } 

} 

/** 
Similarly, the King class inherets most of the behaviors and states from class 
Piece, it must only provide the specific logic necessary to determine whether a 
move is legal for a King. 
**/ 
class King extends Piece 
{ 
   public boolean isLegalMove( Position p ) 
   { 
// Insert Kingís legal move logic here!! 
   } 

}



 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.