Chapter VIII
Creating Object Methods
Chapter VIII Topics
8.1 Introduction
8.2 Creating New Objects
8.3 Constructors
8.4 Using Private and Public
8.5 The CardDeck Case Study
8.6 The Bank Class Revisited
8.6 Method Summary
8.1 Introduction
Object Oriented Programming will not be casually
mentioned in this chapter. OOP is the
front-center topic right now and the intention is to cover some very
introductory OOP ground. Right now you
have a variety of basic Java tools under your belt and you are ready to learn
about this very fascinating modern approach to programming.
Now keep in mind that the single most important goal
for any program is reliability. Speed is great, user-friendly is requested,
cheap is desirable, but nothing matters if the software does not work
properly. First and foremost a program,
or program module, must perform its intended task correctly, the first time,
the last time and every time in between.
There used to be a time in the early days of programming that the
simplicity of the programs and the genius of the computer scientists kept
reliability pretty much afloat with hard work and an organized approach to
programming. In particular, programming
became popular by dividing a program into manageable blocks, and concentrate on
completing and testing the smaller blocks.
Names like structured programming,
modular programming, procedural programming, became important
buzzwords.
Keep in mind that early programs only produced text
output. You should know text output,
because all your lab assignments have produced text output so far. With the arrival of Graphical User Interface (GUI)
the world of programming changed very dramatically, and program complexity has
been growing exponentially every since.
A new style of programming came on the scene slowly, at first, but
rapidly gained momentum and brought about a whole new way of thinking about
programming. Now it matters little if
impressive vocabulary is tossed around.
The bottom line is still reliability,
and as you gain more computer science knowledge you will see how Object
Oriented Programming in general and Java in particular do an outstanding job to
make programs more reliable.
In an earlier chapter you were told that the corner
stones of OOP are encapsulation, polymorphism, and inheritance. Some
introduction to encapsulation happened earlier during the previous two
chapters. This chapter will continue to
explore encapsulation and pick up the pace dramatically.
Programs involve data and the modules that access
and process the data. The problem in the
past has been that the data and the modules processing the data, called procedures and functions, were separated.
This approach caused serious reliability problems. As programs grew in size so did the
likelihood that some procedure or function accessed data unintentionally
and made unwanted and often disastrous changes to data values. A new style of thinking helped prevent
these kinds of problems. This style of
thinking revolves around objects. Objects store data and objects also store
the modules, called methods in Java, which process the data. So far the object seems no different from
programs that combine data storage and procedures that process the stored
data. What makes objects unique is that
every object has its own set of methods, which are unique to the object and the
object stores the data that is appropriate for the object. Furthermore, special precautions are designed
into the object to insure that data is properly initialized and accessed. As a matter of fact, a proper object will not
allow anything outside the object to access its data directly for fear of
potential problems. A well-designed
object carries its own methods that safely handle the object data.
So what does this all mean? This means you have encapsulation, which is a fancy, but very appropriate word. The data and the methods that act upon the
data are all contained in one package, called an object. Multiple objects can be created for multiple
purposes. You can also think of this
package as a capsule, a container, and hence the word encapsulation.
Now we must get clear on the vocabulary used with
objects. You have heard me talk about
actions, subroutines, processes, procedures, functions, and methods. All these words have been used intentionally
because you will probably find every term used somewhere in computer
science. Each one of those words implies
some program module that performs a task, frequently involving data, but not
always. However, some task is always
involved that must be accomplished.
Life would be simpler if computer scientists could
just make up their minds about the naming of these program modules. FORTRAN and BASIC started with subroutines, Pascal followed by having
both procedures and functions, and C++ wanted every module
to be called a function. You will be pleased to know that the current
fashion is to use the word method,
and Java error messages will be using that terminology. From here on method will be used. Keep
the following object vocabulary in mind.
|
Objects, Variables and
Methods |
|
Java
encapsulates data and action modules that access the
data in one container, called an object. Object
members that perform some task are called methods. Object
members that store data are called attributes. |
This is not your first trip on the methods merry-go-around. You have
already learned about using class
methods and using object methods in
an earlier chapter. You have also
learned how to write class
methods. This chapter will round out the
difference between writing a class method and an object method for
you. There are many program examples
provided. Most of the examples are
sequential and need to be examined in their proper order.
|
Important
Note Expect to read this
material a number of times. Many
concepts will be new and foreign to you.
Even small, well-presented program examples, do not always make sense
during the very first introduction of a new topic. |
8.2 Creating New Objects
Let us start with some familiar ground. I will start by showing a program that uses
the features introduced during Chapter V.
In that chapter you learned about class methods. Essentially, you learned that there are
classes already provided by Java, such as the Math class that can be used by programmers. If class methods need to be used, you start
by using the class identifier,
followed by a dot, and then the method identifier, like Math.sqrt(16).
If you want to create your own class methods, it is
very important to use the reserved word static.
Static
or class methods can be accessed
with the class identifier. Now that all
worked rather lovely in Chapter V, and you might wonder why there is need to
rehash this, and why make a distinction between a class and an object
anyway. How about keeping life simple
and just stick to class methods.
Look at program Java0801.java,
in figure 8.1, and review the Java syntax for using class methods. The program example uses a Piggy class, which is short for piggy
bank. The class variable or attribute is
savings and the class methods are initData, addData and showData. initData initializes savings to 0, addData stores data in savings and showData displays the savings
value. Each method in a different way
interacts with the savings
attribute. Everything required to
manipulate the savings data is
handled inside the Piggy class.
Figure 8.1
|
// Java0801.java // This program
introduces the Piggy class, which will be used // to demonstrate a
variety of Object Oriented Programming features. // This program
uses static class variables and static class methods. // Every Piggy
method is accessed using the Piggy class identifier. public class
Java0801 { public static void main(String args[]) { System.out.println("\nJAVA0801.JAVA\n"); Piggy.initData(); Piggy.showData(); Piggy.addData(1200); Piggy.showData(); System.out.println(); }
} class Piggy { static double savings; public static void initData() { savings = 0; } public static void addData(double s) { savings += s; } public static void showData() { System.out.println("Savings:
" + savings); } } |
|
Java0801.java
Output JAVA0801.JAVA Savings: 0.0 Savings: 1200.0 |
This program shows little excitement, but it should
demonstrate a very important point. If Piggy is a class, and the methods in
the class are static, it means that
there cannot be multiple critters of the Piggy
class lurking about. There is one Piggy class, and that is it. Such a situation is quite desirable for
something like a Math class or a Geometry class. The square root of 16 will always be 4 in a
base-10 number system. This means that
there is little need for multiple copies of the Math class. The same is not
true in other situations. The Piggy class may be ideal to manipulate
the bank accounts of many customers.
Using Piggy as shown in
program Java0801.java will limit the
use of Piggy and is not very
practical.
The reserved word static is the culprit here and it prevents the creation of any
additional Piggy copies, called
objects. We will start by removing all
the static words and see if that helps our cause. Program Java0802.java,
in figure 8.2, is identical to the
previous program, minus all the static words.
Figure 8.2
|
// Java0802.java // This program
removes the static keyword from the members of the // Piggy
class. The program no longer compiles. public class
Java0802 { public static void main(String args[]) { System.out.println("\nJAVA0802.JAVA\n"); Piggy.initData(); Piggy.showData(); Piggy.addData(1200); Piggy.showData(); System.out.println(); }
} class Piggy { static double savings; public void initData() { savings = 0; } public void addData(double s) { savings += s; } public void showData() { System.out.println("Savings:
" + savings); } } |
Terrific idea to remove static. Now the program does not even compile anymore
and look at all the error messages in the output of Java0802.java. Do note that
the error message show a pattern. There
are a repeating number of messages that all state that a non-static method Blah-blah cannot be referenced from static contexts.
Figure 8.2 continued
|
Java0802.java
Output Java0802.java:11: non-static method
initData() cannot be referenced from a static context
Piggy.initData(); ^ Java0802.java:12: non-static method
showData() cannot be referenced from a static context
Piggy.showData(); ^ Java0802.java:13: non-static method
addData(double) cannot be referenced from a static context
Piggy.addData(1200); ^ Java0802.java:14: non-static method
showData() cannot be referenced from a static context
Piggy.showData(); ^ 4 errors |
Removing the static
words is correct, but it is not enough.
With static you are only
concerned about using a permanent class, like Math, or any other class.
Only a single copy of the class is created and the same copy is shared
by all users. In many other cases you
require multiple copies or instances of
the class, which are called objects. Using an object requires that memory space is
first allocated for the object and that is done with the new operator. It is now
possible to have many objects of the Piggy
class, and each object stores its own data.
Access to members of a Piggy object is almost
identical to accessing class members.
Use the object identifier (in place of the class identifier), followed
by a dot, and follow the dot with
the method identifier.
Program Java0803.java,
in figure 8.3, will now
compile. Static is removed and tom is
constructed as an object of the Piggy
class. Note that the program statements
now say tom.showData() and tom.addData(); and do not say Piggy.showData(); This is
not a trivial difference. Understanding
the difference between objects and classes is incredibly important.
Figure 8.3
|
// Java0803.java // In this program
a tom object of the Piggy class is instantiated. // The program
compiles now because the methods of the Piggy // class are
treated like "object" methods. public class
Java0803 { public static void main(String args[]) { System.out.println("\nJAVA0803.JAVA\n"); Piggy tom = new Piggy(); tom.initData(); tom.showData(); tom.addData(1200); tom.showData(); System.out.println(); }
} class Piggy { double savings; public void initData() { savings = 0; } public void addData(double s) { savings += s; } public void showData() { System.out.println("Savings:
" + savings); } } |
|
Java0803.java
Output JAVA0803.JAVA Savings: 0.0 Savings: 1200.0 |
The previous program example convinced you rather
poorly that this object creation is such a good thing. It looks like extra work, using the new operator, and what exactly did you
gain? Not much in program Java0803.java, but look at figure 8.4
and note that program Java0804.java creates
multiple Piggy objects. If int
or double only allows access to a
single memory location, it will not be very practical. What this means is that an object is one instance of a class. The class is the type
and the object is the variable. The
statement int X; allocates space for
an integer variable during compiling. A
slightly more complicated statement is required to bring an object to
life. Program Java0804.java in figure 8.4 constructs two objects of the Piggy
class. Each object stores its own data.
Figure 8.4
|
// Java0804.java // This program
constructs multiple objects of the Piggy class. // Using objects
allows storing information in multiple instances // of the Piggy
class. This is not possible with
static methods. public class
Java0804 { public static void main(String args[]) { System.out.println("\nJAVA0804.JAVA\n"); Piggy tom = new Piggy(); tom.initData(); tom.addData(1200); tom.showData(); Piggy sue = new Piggy(); sue.initData(); sue.addData(2500); sue.showData(); System.out.println(); }
} class Piggy { double savings; public void initData() { savings = 0; } public void addData(double s) { savings += s; } public void showData() { System.out.println("Savings:
" + savings); } } |
|
Java0804.java
Output JAVA0804.JAVA Savings: 1200.0 Savings: 2500.0 |
8.3 Constructors
All four of the program examples shown so far
featured the initData method. Method initData
serves the important purpose of initializing the variable attributes of the Piggy objects. The habit of initializing variables was shown
early in the course with simple data types that used statements like:
int Sum = 0;
double PayRate = 5.25;
It is a good habit to initialize variables, and it
is also a good habit to initialize the attributes of any objects that are
created. But there is a problem, and the
problem is the word habit. What if you have not acquired good
habits? Object Oriented Programming is advertised as improving program
reliability. At least some author with a
strange Dutch name seems to believe that OOP is the world greatest gift to
reliable programming. In other words,
you are not impressed with the initData method
and rightfully so. You should not be
impressed. Perhaps program Java0805, in figure 8.5, will impress you more.
Figure 8.5
|
// Java0805.java // This program
exchanges the initData method with the Piggy constructor. // Constructors add
reliability to programs because they are called // automatically
during the instantiation of a new object. public class
Java0805 { public static void main(String args[]) { System.out.println("\nJAVA0805.JAVA\n"); Piggy tom = new Piggy(); tom.showData(); tom.addData(1200); tom.showData(); System.out.println(); }
} class Piggy { double savings; public Piggy() { System.out.println("Constructing
a Piggy object"); savings = 0; } public void addData(double s) { savings += s; } public void showData() { System.out.println("Savings:
" + savings); } } |
|
Java0805.java
Output JAVA0805.JAVA Constructing a Piggy object Savings: 0.0 Savings: 1200.0 |
Now program Java0805.java
requires some closer scrutiny. The initData method is gone. In its place is an odd looking method that
initializes the savings variable and
the method identifier looks especially strange.
It appears that the method has the exact same name as the class. Both
are named Piggy. It gets stranger. Check out the main method. There you see tom ready to become a Piggy object
followed immediately by a call to the showData
method.
Now look closely at the execution. First it displays JAVA0805.JAVA
and that makes
sense since it is the first println statement
in the main method. The next output is Constructing a Piggy object and that makes little sense. There is no such output statement in main.
The third output line Savings: 0.0 does make sense because it
is the result of the call to method ShowData. This means that the statement Piggy tom = new Piggy(); must be responsible for the odd output. Now look at the beginning of the program,
inside the Piggy class. You will find a
println statement in the Piggy method that could account for the mysterious
display. This means that this odd method
is somehow called during the creation of the new object. This special method is called a constructor.
We gained something very significant here. In the previous program it was required to
call the initData method to insure
that the new object is properly initialized.
Now this is no longer necessary.
A special constructor method is included in the Piggy declaration and this method is called automatically with the new operator when an object is first
instantiated, constructed or created.
Lots of words, but they all have the same meaning.
|
Instantiation and
Construction |
|
A
class is a template that can form
many objects. An
object is a single variable instance of a class. Objects are sometimes called instances. An
object is created with the new operator. The creation of
a new object is called: instantiation
of an object construction
of an object The
special method that is called during the instantiation of an
object is called a constructor. |
The new Piggy
constructor is shown in figure 8.6.
The println statement is included
to prove the point that the method is called, and where the method is
called. This leaves the rather
unimpressive savings = 0; statement in the constructor to take care of
business. It is not impressive, but it
is a minimal sort of constructor that at least assigns some value to savings.
Figure 8.6
|
Piggy() { System.out.println("Constructing a
Piggy object"); savings = 0; } |
There are other more practical constructors. It is possible to use parameters and pass
specific information to a constructor during instantiation. This allows control over the manner in which
a new object is constructed.
Furthermore, it is possible to have multiple constructors in a class for
different purposes. Program Java0806.java in figure 8.7
demonstrates the Piggy class with two constructors. The second constructor provides a name and a savings amount.
Figure 8.7
|
// Java0806.java // This program
demonstrates that constructors can be overloaded. // It is possible
to supply information, using parameters, to the // new object at
the instance that it is constructed. public class
Java0806 { |