OOP "Template" Class - Part 2


A class is a fundamental grouping of programming data and instructions. Usually applications are made up of several, if not hundresds of classes, which make instances of each other to accomplish various tasks. So each class is specialized to do certain tasks within an applications. Microsoft Word, for example, probably has classes specialized in spell checking, others specialized in formatting of words, and others still specialized in saving and opening. And there is at least one class in all applications which has a main method. But most classes are what I term a "template" class; they are classes that allows the creation of objects of them, but don't have a main method for running.

Classes Are Made Up of Attributes and Methods

Everything in a class is either a data type, which we'll call an attribute, or a method which somehow uses or manipulates one or more of the attributes. Usually we list the attributes with global scope at the top of the program, and then the rest of the program is the various methods that work with these attributes.

The first page of notes about "template" classes had one major omission regarding good Object Oriented Programming (OOP) design; it left the attributes without the word "private" in their declaration. This should never actually done - in our case it was done simply to keep the instruction as simple as possible for the first notes. But with these notes, we can take a look at what is necessary when you properly make your attributes private: "get" and "set" methods.

The Reason For Private Attributes

With programming constructs prior to the advent of OOP, it was common practice for different classes to share attributes - in fact to share whole libraries of data. But this led to unreliable programs because programmers would end up writing code which altered certain attributes ways that caused problems for other classes that used them. The classic example here is how Windows applications used to share "dll" libraries - Dynamically Linked Libraries. There are real benefits to sharing, and they are primarily related to memory saving issues. But now-a-days, with vast amount of RAM memory, and secondary storage, there is no need to risk the problems associated with sharing attributes, let alone full libraries of data. Rather, OOP constructs speak of "encapsulation", in which the attributes and methods that manipulate them, of a certain class, are all bundled together, and protected from other classes potential misuse of those attributes.

Private Attributes, Public Methods

So, when we make template classes, we will always make all of the attributes of that class private. The will not be able to be accessed directly by other classes, using dot notation, as we saw in the first part of the Template Class notes. This means that any accessing or changing of these attributes will have to take place via public methods - methods that are fully under the control of the programer making the class. Only the method header, and its specific "signature" of it can be seen by other programmers using the method. The header and the signature of a method for our purposes at this point the same thing - they are the first line of the method. And that will tell the user of it (from another class) the method name, what it returns, and the number and type of parameters that are needed to properly use it. We say that this header line of all the public methods therefore make up the public interface of a class - they are what the users of the class can see as pubicly accessible.

So, in Netbeans, for example, when we make an instance of an class, and then type it and type a dot, we see a list of all the things that are available to use - i.e. all of the public things, which is properly just the methods. Though you'll note that there are both the methods which we have created, but also any of the methods inherited from other classes, in particular the Object class, which all other classes, including the ones we make, are decendants of.

All the above methods in bold are ones that we made in our EndangeredSpecies class, and all the others come from the Object class, from which all other classes are decended. See the class below to note this. The only other public interface methods not listed above are the contructors themselves.

One other thing to note above from the Netbeans snapshot is that the paramerter list is in the parentheses as normal, but the return values are off to the right.

 3 package endangeredspecies;
 6 public class EndangeredSpecies {
 8     //The "attributes"
 9     private String speciesName = "not set yet";
10     private int numberLeft = 0;
11     private boolean critical = false;
13     //The "CONSTRUCTORS" - we'll make two; the default, and one other.
15     //The Default Constructor
16     public EndangeredSpecies(){
18     }
20     //The First Overloaded Constructor - this one takes in one piece of information - it sets the speciesName only.
20a    //Note that overloaded constructors are an example of "polymorphism"
21     public EndangeredSpecies(String speciesName){
22         this.speciesName = speciesName;
23     }
25     //The Second Overloaded Constructor - this one sets all three attributes to values passed to it.
27     //In fact, we don't use this one in the program the way it works now, but we should implement
28     //it for possible future use as the GUI is worked on.
30     public EndangeredSpecies(String speciesName, int numberLeft, boolean critical){
31         this.speciesName = speciesName;
32         this.numberLeft = numberLeft;
33         this.critical = critical;
34     }
37     /*The "Set" Methods - one for each attribute,
38     for setting the attributes of a particular Team object.*/
39     public void setSpeciesName(String speciesName){
40         this.speciesName = speciesName;
41     }
42     public void setNumberLeft(int numberLeft){
43         this.numberLeft = numberLeft;
44     }
45     public void setCritical(boolean critical){
46         this.critical = critical;
47     }
49     /*The "Get" Methods - one for each attribute,
50     for sending back particular information about a particular Team object.*/
51     public String getSpeciesName(){
52         return speciesName;
53     }
54     public int getNumberLeft(){
55         return numberLeft;
56     }
57     public boolean getCritical(){
58         return critical;
59     }
60     //Other "Mutator" Methods
61     /*This is the other method, which in this case adjusts the number left based on the number killed.*/
62     public void adjustNumberLeft(int numberKilled){
63         numberLeft -= numberKilled;
64         if(numberLeft < 1000){
65             critical = true;
66         }
67     }
67a    //You should get into the habit of also including "overriding" of the Object method toString, another example of polymorphism.
67b    public String toString(){
67c        return "Species name: " + speciesName + ", number left: " + numberLeft + ", critical: " + critical + ".";
68     }
69 }

The Four General Kinds of Methods in a Template Class

1. Constructors

The constructors are the means of making instances of classes, so that other classes can access their methods. The constructor is unique the way it is written for two reasons, it is exactly the same name as the class (even capitalized), and it has no return method, not even void. But it can take parameters, though it doesn't have to. In fact, there can be more than one constructor, with the different constructors taking in differnt numbers and kinds of parameters. So, for example, in the program above, it is possible to construct a new EndangeredSpecies object with just an initial speciesName attribute, or we can make a new object of the EndangeredSpecies class and set values to all three variables. And we can even construct a new EndangeredSpecies object without setting any of the attributes at the time of construction. And you'll note that this default constructor does not need to be explicitly written by us; it is compiled behind the scenes regardless.

The Implementation of the Constructors of the EndangeredSpecies Class:

16     public EndangeredSpecies(){
17         speciesName = "";
18     }
21     public EndangeredSpecies(String speciesName){
22         this.speciesName = speciesName;
23     }
30     public EndangeredSpecies(String speciesName, int numberLeft, boolean critical){
31         this.speciesName = speciesName;
32         this.numberLeft = numberLeft;
33         this.critical = critical;
34     }

When constructors are called by other classes making instances of a certain class, the new operator is used to find a free block of memory apporpriately sized for that class. In the case of the example here, that would be enough memory for one String, one int, and one boolean. (This was shown in the last notes, too.) Here is a line using the above first "overloaded" constructor:

NewClass.java Calling One of the Constructors of the EndangeredSpecies Class
14     EndangeredSpecies es = new EndangeredSpecies("Humpback whale");

2. "Set" Methods

The set methods are very similar to the constructors in that they take in parameters, and don't return anything. The are there so that the various attributes can be altered as the program is used. Refer to the code above to see what they look like. And keep in mind that we can initially assign values to the various attributes through the constructor, but then potentially change these for any attributes that have set methods.

3. "Get" Methods

Since we want our attribues to be private, if we are going to access their values, we will need public methods that return their values. This is exactly what get methods do. Refer to the full program above to see what they look like. But as you would expect, they do return the type of the specific attribute, and they take in no parameters.

4. Other Data Manipulation "Mutator" Methods

We can group all of the other methods of a class into this category. In fact, in the grand scheme of things these will be the most important methods, since they don't just set or get attributes which could have otherwise just been declared in the calling class. Rather, these supply the real data manipulation algorithms of the program. Our program above is very simply, but you can imagine that there are an infinite variety of complex things that such methods do.

A Class That Uses Our Template Class

Here is the code for a GUI that uses the above template class. For these notes, it's not necessary to understand all of it, but it is included here for a sense of completion. Primarily look for where instances of the EndangeredSpecies class is made, and where the various methods are called.

 12 package endangeredspecies;
 18 public class EndangeredGUI extends javax.swing.JFrame {
 20     private EndangeredSpecies[] speciesArray = new EndangeredSpecies[10];
 21     private int arrayCount = 0;
 24     public EndangeredGUI() {
 25         initComponents();
 26         myinitComponents();
 27     }
 28     public void myinitComponents(){
 29         for(int i = 0; i < speciesArray.length ; i++){
 30             speciesArray[i] = new EndangeredSpecies();
 31         }
 32         jComboBoxForNames.setModel(new javax.swing.DefaultComboBoxModel(new String[] { }));
 34     }
286     private void jButton1MouseReleased(java.awt.event.MouseEvent evt) {
288         speciesArray[arrayCount].setSpeciesName(jTextFieldNameEntered.getText());
289         speciesArray[arrayCount].setNumberLeft(Integer.parseInt(jTextFieldPopulationEntered.getText()));
290         arrayCount++;
291         System.out.println(speciesArray[0].getSpeciesName());
292     }
294     private void RefreshMouseClicked(java.awt.event.MouseEvent evt) {
296         for(int i = 0; i < speciesArray.length; i++){
297             jComboBoxForNames.addItem(speciesArray[i].getSpeciesName());
298         }
299     }
301     private void jButton2MouseClicked(java.awt.event.MouseEvent evt) {
303         String selectedSpecies = jComboBoxForNames.getSelectedItem()+"";
304         for(int i = 0; i < speciesArray.length; i++){
305             if(speciesArray[i].getSpeciesName().equals(selectedSpecies)){
306                 speciesArray[i].adjustNumberLeft(Integer.parseInt(jTextFieldAdditionalKilled.getText()));
307                 if(speciesArray[i].getCritical()){
308                     jLabelWarning.setForeground(java.awt.Color.RED);
309                     jLabelWarning.setBackground(java.awt.Color.RED);
310                     jLabelWarning.setText("Warning!!! Critical!!!");
311                     jLabelWarning.setAlignmentX(2);
312                 }
313             }
314         }
316     }
321     public static void main(String args[]) {
322         java.awt.EventQueue.invokeLater(new Runnable() {
323             public void run() {
324                 new EndangeredGUI().setVisible(true);
325             }
326         });
327     }