Lecture 18

CSC120: Programming I - Fall 2000
Christian A. Duncan
(305) 284-2254
csc120@ocala.cs.miami.edu
Office hours: Tuesday and Thursday (1-3 PM)

Announcements

Public vs. Private

This section was covered on lecture 18 notes, but we did not go over it so it is repeated again.

Here it comes finally. Until now, everything has been public this and public that. What does that really mean?

public class WeaponList {
  private int tally;
  private String[] weaponName;

  public WeaponList(int maxSize) {
    weaponName = new String[maxSize];
    tally = 0;
  }

  public void addWeapon(String weaponToAdd) {
    if (tally < weaponName.length) {
      // Still space left to add more names
      weaponName[tally] = weaponToAdd;
      tally++;
    } else {
      // No space let, we'll do nothing (for now)
    }
  }

  public void printWeaponList() {
    int i;
    while (i < tally) {
      System.out.println("Weapon " + i + 
        ": " + weaponName[i]);
      i++;
    }
  }

  public String getWeaponAt(int i) {
    if ((i < 0) || (i >= tally)) {
      // Out of range
      return null;
    } else {
      return weaponName[i];
    }
  }

  public int getTally() {
    return tally;
  }
}
In this example, if we tried to directly access the variable tally or the array name, we would get an error (at compilation time). To see this better, look at the following commands:
   WeaponList wList = 
     new WeaponList(100);	  // Valid, constructor is PUBLIC
   wList.addWeapon("Sling");	  // Valid, method is PUBLIC
   wList.addWeapon("Mace");	  // Valid, method is PUBLIC
   wList.printWeaponList();	  // Valid...
   wList.tally = 10;		  // Invalid... variable is PRIVATE
				  // why is this very IMPORTANT?
   wList.weaponName[20] = "Axe";  // Invalid... again why is this IMPORTANT?
So, now we see that we can prevent variables from being changed. Why? Imagine the other class chose to add weapons themselves, simply placing values into the array without calling the method. Then, it decides to call the method to PRINT the list. Guess what? The object can't. Why not, b/c the tally was not incremented at the same time. The object (wList) does not know how many weapons were added by the outside classes... it still thinks there are 0.

Of course, we could expect the outside class to increment the tally as well. But this defeats the purpose of writing a class to handle the task. Second, if the outside class had access to the tally variable, they could mistakenly change that value. For example, setting it to 10 when there are only 5 weapons, or 5 when there are in fact 10 on the list. In both cases, printing out the list (or whatever other methods there are for the class) would not work.

But, what if the outside class really wants to access a value or change one. And you also want the outside world to have some (limited) access to these variables. Sometimes this is necessary. You solve this by writing accessor methods.

Accessor Methods

Accessor methods allow other classes to access private variables.

In the above example, getTally() and getWeaponAt(int index) are both accessor methods to tally and the weaponName array. You may also have methods to set variables. In general, the naming convention is as follows:

Remember this is just a convention. What you choose to name something is entirely up to you. For example, for the variable tally we would have two methods:
   public int getTally() {
     return tally;
   }

   public void setTally(int newTally) {
     tally = newTally;
   }
Of course, in this example, it doesn't make sense to have setTally as a method at all, or at least not a PUBLIC method (maybe PRIVATEly would be reasonable.) But there are cases where you would allow setting the variables with a method. Essentially, the accessor method can control the access of the value set or "gotten".

Private Methods

Variables are easy, they should nearly ALWAYS be private. Methods are a bit tricky. Generally, they are public. Sometimes though, you write methods which are used to handle stuff inside the class but do not and should not be used by others outside of the class.

This is a harder rule to describe. If the method should be accessible outside, then make it public, if not, make it private. So, in practice, try to follow these rules and you'll be fine:

Interfaces

In lab this week, you learned (will learn) about using interfaces. An interface is a way of defining behavior for classes. It allows us to describe ways other classes can interact with another group of classes. Interfaces are defined by the following technique:
public interface Locatable {
  public int getLocationX();
  public int getLocationY();
}
This definition implies that any object which is Locatable must have two methods (getLocationX() and getLocationY()) implemented. Here is how we would define such a class.
public class Human implements Locatable {
  Stats theStats;
  int positionX;
  int positionY;
  
  // ...
  // Insert lots of methods and other variables here
  // ...
  // ...

  public int getLocationX() {
    return positionX;
  }

  public int getLocationY() {
    return positionY;
  }
}
Here, we created a class Human which implements the interface Locatable. What this means is that we are promising to implement the methods associated with the interface Locatable.

In fact, somewhere inside the definition we actually implement these methods, getLocationX() and getLocationY(). In this case, we ignored all the other methods, but they would be there as well. Now, we can say that Human is Locatable.

Note: when it comes to naming interfaces, it is customary to use adjective names ending in "able"... e.g., Enumerable, Countable, Throwable, etc.

Using interfaces it is possible for another unrelated class to also implement the same interface. For example,

public class Item implements Locatable {
  String itemName;
  int coordinateX;
  int coordinateY;

  // ...
  // Insert lots of methods and other variables here
  // ...
  // ...

  public int getLocationX() {
    return coordinateX;
  }

  public int getLocationY() {
    return coordinateY;
  }
}
Again, this class Item implements Locatable meaning that any instance of Item has (among its numerous methods) the two methods (getLocationX() and getLocationY()). Two more important features of interfaces: The last part may be a bit hard to grasp. Let us illustrate interfaces with a simple use.
   Human personOne = new Human("Miss Scarlet");
   Human personTwo = new Human("Colonel Mustard");
   Item itemOne = new Item("Candlestick");
   Item itemTwo = new Item("Wrench");

   int x;
   int y;

   // These methods all work
   x = personOne.getLocationX();
   y = personOne.getLocationY();
   x = itemOne.getLocationX();
   y = itemOne.getLocationY();
   
   Locatable objectToLocate;
   objectToLocate = personTwo;
   x = objectToLocate.getLocationX();
   y = objectToLocate.getLocationY();

   objectToLocate = itemTwo;
   x = objectToLocate.getLocationX();
   y = objectToLocate.getLocationY();

  // The following does NOT work
  objectToLocate = new Locatable();
  // Locatable objects cannot be created.   
On Thursday, we shall go over a Java example using Vectors. This requires understanding of interfaces, not creating them but simply knowing how to use them and what they mean. Make sure you read up on the chapters and lecture notes.