Summary: Learn about abstract methods, abstract classes, and overridden methods. You will also learn about overriding the toString method.
This module is one of a series of modules designed to teach you about Object-Oriented Programming (OOP) using Java.
I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the images and listings while you are reading about them.
The program that I will explain in this module produces no graphics and does not require the use of Ericson's media library.
OOP concepts
The program illustrates the following OOP concepts:
Program specifications
Write a program named Prob04 that uses the class definition shown in Listing 1 to produce the output on the command-line screen shown in Image 1 .
| Image 1: Program output on the command line screen. |
|---|
|
Pseudo random data
Because the program generates and uses a pseudo random data value each time it is run, the actual values displayed in the last two lines of Image 1 will differ from one run to the next. However, in all cases, the two values must match.
New classes
You may define new classes as necessary to cause your program to behave as required, but you may not modify the class definition for the class named Prob04 given below.
Will explain in fragments
I will explain this program in fragments. A complete listing is provided in Listing 5 near the end of the module.
I will begin with the driver class named Prob04 , which is shown in its entirety in Listing 1 .
| Listing 1: Source code for class Prob04. |
|---|
|
The import directive
The import directive at the beginning of Listing 1 is required because the program requires access to the Random class and the Date class, both of which are defined in the java.util package.
Lazy programming practice
It would be better programming practice to provide two explicit import directives, one for the Random class and the other for the Date class. However, if you are lazy like I apparently was when I wrote this program, you can use the wildcard character (*) to import all of the classes in a package.
An abstract method
I'm going to begin by skipping down to the second line from the bottom in Listing 1 and explain the declaration of the abstract method named getData .
Purpose of an abstract method
The purpose of an abstract method declaration is to establish the signature of a method that must be overridden in every (non-abstract) subclass of the class in which the abstract method is declared.
An incomplete method
As you can see the abstract method has no body. Therefore, it is incomplete, has no behavior, and cannot be executed.
An abstract method must be overridden in a subclass in order to be useful.
Override in different ways
The same abstract method can be overridden in different ways in different subclasses. In other words, the behavior of the overridden version can be tailored to (appropriate for) the class in which it is overridden.
A guarantee
The existence of an abstract method in a superclass guarantees that every (non-abstract) subclass of that superclass will have a concrete (executable) version of a method having that same signature.
An abstract class
The class named Prob04 is declared abstract in Listing 1 .
Any class can be declared abstract. The consequence of declaring a class abstract is that it is not possible to instantiate an object of the class.
Must be declared abstract...
More importantly, a class must be declared abstract if it contains one or more abstract method declarations. The idea here is that it must not be possible to instantiate objects containing incomplete (non-executable) methods.
The main method
As you have seen in previous modules, the driver class for every Java application must contain a method named main with a signature matching that shown in Listing 1 .
A pseudo-random number generator
I will leave it as an exercise for the student to go to the javadocs and read up on the class named Random , along with the class named Date and the method named getTime .
Why pseudo-random?
I refer to this as a pseudo-random number generator because the sequence will probably repeat after an extremely large number of values has been generated.
An object of the class Random
Briefly, however, the first statement in the main method in Listing 1 instantiates an object that will return a pseudo-random number each time certain methods are called on the object.
Seeding the generator
The value passed as a parameter to the Random constructor represents the current time and guarantees that the series of pseudo-random values returned by the methods will be different each time the program is run. This is commonly known as seeding the generator.
Get and save a pseudo random value
The next statement in Listing 1 1 calls the nextInt method on the generator object to get and save the next value of type int in the pseudo-random sequence.
Cast to type byte
This value is cast to type byte , which discards all but the eight least significant bits of the int value. When it is stored in the variable named randomNumber of type int , the sign is extended through the most significant 24 bits and it becomes a value of type int that is guaranteed to be of relatively small magnitude.
Why cast to byte?
I cast the random value to type byte simply to cause the values that are displayed to be smaller and easier to compare visually.
Instantiate an object of type Prob04MyClass
The next statement in Listing 1 instantiates an object of the class named Prob04MyClass , passing the random value as a parameter to the constructor. At this point, I will put the explanation of the class named Prob04 on temporary hold and explain the class named Prob04MyClass , which begins in Listing 2 .
| Listing 2: Beginning of the class named Prob04MyClass. |
|---|
|
Extends the abstract class named Prob04
First note that the class named Prob04MyClass extends the abstract class named Prob04 .
Among other things, this means that either this class must override the abstract method named getData that was declared in the superclass, or this class must also be declared abstract.
Does it override getData?
Seeing that this class isn't declared abstract, we can surmise at this point that it does override the abstract method named getData . We will see more about this later.
Beginning of the class named Prob04MyClass
The class definition in Listing 2 begins by declaring a private instance variable of type int named data . Note that it does not initialize the variable. Therefore, the value is automatically initialized to an int value of zero.
The constructor
Then Listing 2 defines the constructor for the class. The first two statements in the constructor cause the first two lines of text shown in Image 1 to be displayed on the command line screen.
Save the incoming parameter value
The last line in the constructor saves the incoming value in the instance variable named data , overwriting the default value of zero that it finds there.
This statement is more in keeping with the intended usage of a constructor than the first two statements. The primary purpose of a constructor is to assist in the initialization of the state of an object , which depends on the values stored in its variables.
Override the abstract getData method
Listing 3 overrides the abstract getData method declared in the abstract superclass named Prob04 and inherited into the subclass named Prob04MyClass .
| Listing 3: Override the abstract getData method. |
|---|
|
Very simple behavior
Although the overridden version of the method simply returns a copy of the value stored in the private instance variable named data , it is concrete and can be executed. We will see later that it is called in the main method of the driver class named Prob04 in Listing 1 .
Override the toString method
The ultimate superclass of every class is the predefined system class named Object . The Object class defines eleven methods with default behavior, including the method named toString .
Listing 4 overrides the inherited toString method, overriding the default behavior of the method insofar as objects of the class named Prob04MyClass are concerned.
| Listing 4: Override the toString method. |
|---|
|
Default behavior of the toString method
If the toString method had not been overridden in the Prob04MyClass class, calling the toString method on an object of the class would return a string similar to that shown in Image 2.
| Image 2: Default behavior of the toString method . |
|---|
|
Image 2 shows the default behavior of the toString method as defined in the Object class. For this program, only the six hexadecimal digits at the end would change from one run to the next.
More on the default behavior of the toString method
Furthermore, if the toString method had not been overridden in the Prob04MyClass class, the output produced by the program on the command line screen would be similar to that shown in Image 3 instead of that shown in Image 1 .
| Image 3: More on the default behavior of the toString method. |
|---|
|
Compare to see the difference
If you compare Image 3 with Image 1 , you will see that the difference results from the fact that the overridden version of the toString method in Listing 4 returns "Baldwin" as a string rather than returning the default string shown in Image 2 .
The end of the class named Prob04MyClass
Listing 4 signals the end of the class definition for the class named Prob04MyClass . Therefore, it is time to return to the explanation of the driver class shown in Listing 1 .
Display information about the object
When the Prob04MyClass constructor returns, Listing 1 calls the println method passing a reference to the new object as a parameter.
Many overloaded (not overridden) versions of println
There are many overloaded versions of the println method, each of which requires a different type of incoming parameter or parameters.
For example, different overloaded versions of the method know how to receive incoming parameters of each of the different primitive types, convert them to characters, and display the characters on the screen.
An incoming parameter of type Object
There is also an overloaded version of the println method that requires an incoming parameter of type Object . That is the version of the method that is executed when the reference to this object is passed to the method in Listing 1 .
One object, several types
Recall that the reference to this object can be treated as its true type, or as the type of any superclass. Therefore, the reference can be treated as any of the following types:
Will satisfy type requirement...
Because it can be treated as type Object , it will satisfy the type requirement for the overloaded version of the println method that requires an incoming parameter of type Object .
Call the toString method
The first thing that this version of the println method does is to call the toString method on the incoming reference. Then it displays the string value returned by the toString method on the screen.
In this case, the overridden toString method returns the string "Baldwin" , which is what you see displayed in Image 1 .
Runtime polymorphism
This is a clear example of an OOP concept known as runtime polymorphism .
Runtime polymorphism is much too complicated to explain in this module. However, I explain it in detail in my online OOP modules and I strongly recommend that you study it there until you thoroughly understand it.
A critical concept
It is critical that you understand runtime polymorphism if you expect to go further in Java OOP.
It is almost impossible to write a useful Java application without making heavy use of runtime polymorphism, because that is the foundation of the event driven Java graphical user interface system.
Call the overridden getData method
The next statement in Listing 1 calls the overridden getData method and displays the return value.
As you saw earlier, this method returns a copy of the random value that was received and saved by the constructor for the Prob04MyClass class in Listing 2 .
Display the original random value
Finally, the last statement in the main method in Listing 1 displays the contents of the instance variable named randomNumber . This variable contains the random value that was passed to the constructor for the Prob04MyClass earlier in Listing 1 .
The two values must match
Therefore, the final two statements in the main method in Listing 1 display the same random value. This is shown in the command line screen output in Image 1 .
The program terminates
After displaying this value, the main method terminates causing the program to terminate.
I encourage you to copy the code from Listing 5 , compile it and execute it. Experiment with the code, making changes, and observing the results of your changes. Make certain that you can explain why your changes behave as they do.
You have learned about abstract methods, abstract classes, and overridden methods in this module. Very importantly, you have learned about overriding the toString method.
You will learn more about indirection, array objects, and casting in the next module.
Select the following links to view online video lectures on the material in this module.
This section contains a variety of miscellaneous information.
Financial : Although the Connexions site makes it possible for you to download a PDF file for this module at no charge, and also makes it possible for you to purchase a pre-printed version of the PDF file, you should be aware that some of the HTML elements in this module may not translate well into PDF.
I also want you to know that, I receive no financial compensation from the Connexions website even if you purchase the PDF version of the module.
In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle books, and placed them for sale on Amazon.com showing me as the author. I neither receive compensation for those sales nor do I know who does receive compensation. If you purchase such a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it was made and published without my prior knowledge.
Affiliation : I am a professor of Computer Information Technology at Austin Community College in Austin, TX.
A complete listing of the program discussed in this module is shown in Listing 5 below.
| Listing 5: Complete program listing. |
|---|
|
-end-