Classes, objects and inheritance

CSC72002
Object Oriented Programming
Topic
Classes, objects and inheritance
©
Southern Cross University
Developed and produced by Southern Cross University
Military Rd, EAST LISMORE. N.S.W. 2480. 2nd Session, 2018.
No part of this publication may be reproduced, stored in a retrieval system or transmitted
in any form of by means electronic, mechanical, photocopying, recording or otherwise
without the prior written permission of the publisher.
Copyright materials reproduced herein are used under the provisions of the
Copyright Amendment Act (1989).
Readings, if any, indicated in this work have been copied under section VB of the Copyright Amendment Act 1989
Copies, if any, were made by Southern Cross University in 2018
for private study only by students.
CAL LICENSED COPY – UNAUTHORISED COPYING PROHIBITED
CSC72002 Study Guide
1-3
Contents
CLASSES, OBJECTS AND INHERITANCE…………………………………………………………………………………………….4
References……………………………………………………………………………………………………………………………………………..4
Objectives………………………………………………………………………………………………………………………………………………4
Introduction……………………………………………………………………………………………………………………………………………4
Classes…………………………………………………………………………………………………………………………………………………..4
Constructors …………………………………………………………………………………………………………………………………………..5
Reference variables and objects ………………………………………………………………………………………………………………..6
Inheritance……………………………………………………………………………………………………………………………………………11
Inheritance in UML Class Diagrams………………………………………………………………………………………………………..13
The super keyword………………………………………………………………………………………………………………………………13
Polymorphism ………………………………………………………………………………………………………………………………………15
The Object class …………………………………………………………………………………………………………………………….15
Polymorphism with Object………………………………………………………………………………………………………………..17
Polymorphism win general………………………………………………………………………………………………………………….18
Summary ……………………………………………………………………………………………………………………………………………..19
Answers to Activities …………………………………………………………………………………………………………………………….20
CSC72002 Study Guide Classes, objects and inheritance
1-4
Classes, objects and inheritance
References
Liang, Y.D. 2015. Introduction to Java Programming – Comprehensive Version, 10th Edition, Pearson,
USA. ISBN:978-1-292-07001-8.
Objectives
This is revision of concepts you have studied previously but may have forgotten. On completion of this
topic you should be again able to:
1. Develop classes to represent real or abstract objects
2. Use inheritance to re-use code in other classes
3. Use constructors, the super keyword and method overriding in your classes
4. Describe how objects created from classes are managed by the Java run-time
5. Use polymorphism in class hierarchies
Introduction
This topic is revision of concepts you have already studied and used in prerequisite units. We will only
revise ideas that will be important for the remainder of this unit. We will also use the technical terms
for some topics that you will find in the textbook. Do not be too worried when you come across some
of the terms, they are referring to things your already know about and used in earlier units.
In this topic we will first revise classes and their components. We will then introduce informal box and
arrow diagrams which may help you understand how Java manages objects at runtime. Basic
inheritance will then be revised and finally polymorphism will be examined, though you may know this
concept by other names.
In the examples in this topic we will always use example code that is different than the code in the
textbook. This is to give you additional examples to read and try in the activities.
Classes
As you have already learned, a class is a template for creating objects. We say an object has a type,
which is the class that was used to create it. There are other types besides classes. You will have the
primitive types (int, float, bool, etc.) and we will see more complex types later in the unit.
There are several basic elements of a class that you have seen previously:
– class name
– attributes (data definitions)
– constructors and destructors
– methods
All classes have a name but the other parts of a class are optional.
The following is a simple class to represent an object that represents an animal. It has one attribute, a
constructor and one method.
CSC72002 Study Guide Classes, objects and inheritance
1-5
public class Animal
private String species;
Animal(String s)
species = s;

public String getSpecies()
return species;

Once we have the class defined we can create objects of this class type and initialise the attributes with
the constructor with statement like the following.
Animal dog = new Animal(“dog”);
Animal cat = new Animal(“cat”);
There are several things about the design of this class that you will have learned previously. After all,
we could represent the same data as a simple variable declaration, e.g.
String dog = “dog”;
The class definition imposes addition features to our simple primitive data representations. The species
attribute is declared as private. This means that it is not accessible except through the methods
of the class. This is sometimes called data hiding. Its advantage is that access to the data is filtered
through the class methods so the data’s state can be controlled by the class designer. In this case, the
data cannot be changed after it is initialised by the constructor because the class does not have a mutator
or setter method to change its value. Objects such as these are called immutable objects.
To access the data in an object we must use methods defined in the class. The methods defined as public
can be called using the dot notation you will be familiar with. For example, if we wish to display on
the console the data in the dog object created with the new statement above, we can code:
System.out.println(dog.getSpecies());
Here, the dot notation is used to access the public getSpecies() method associated with the object
referenced by the dog variable. We will examine what “reference” means later.
The final thing to note about classes before you attempt a practical activity is that in Java we usually
define them in their own file. The file name must match the class name. The advantage of this is that
the class can be re-used as it will be compiled separately and therefore can be incorporated in other
projects. “re-use” is an important feature of object-oriented languages which drives some of the features
we will look at later in the unit.

 Activity 1-1: Classes
1. Implement the above class and the statement to print the species name on the console.
The class should be defined in its own file. In NetBeans you can select “file”, “New
File…”, “Java”-“Java class” and enter the class name. The declaration of the objects
and the println() calls are placed in the main() method of your program.
2. Read the textbook Section 9.1-9.3 (pp 344 – 351)
3. Try the TV example from the reading.

Next, we look at constructors.
Constructors
A constructor is used to initialise an object. We have already seen a simple constructor above which
initialised object of the Animal class we defined. A constructor has exactly the name as the class and
we can overload constructors to provide multiple constructors which are selected based on their
CSC72002 Study Guide Classes, objects and inheritance
1-6
signature, which is the number and types of the parameters. Constructors can have as many parameters
as you like, but the case of no parameters needs further explanation.
If a class had no constructors defined, Java provides a default constructor. This can be thought of as
initialising the attributes of the class to their normal default values. However, if we define one or more
constructors the default constructor is not available any more. Using the previous class definition, the
following statement will cause a syntax error:
Animal unknown = new Animal(); // syntax error
If we need a default constructor then we must implement one in the class definition. For example, we
can modify the Animal class from the previous section as follows.
public class Animal
private String species;
Animal(String s)
species = s;

Animal()
species = “unknown”;

public String getSpecies()
return species;

Now, the statement above using the default constructor will compile successfully and the species data
will be initialised with the string “unknown”.
Activity 1-2: Interfaces
1. Read the textbook Section 9.4 (p. 351)
2. Verify that a syntax error occurs when you add the above statement with the default
constructor.
3. Add the default constructor above and add another console output statement to display
the object created with the default constructor.
We will now look at reference variable and objects, something you have been using but may not have
though much about.
Reference variables and objects
You have been using reference variable in your Java programming but may not have thought very much
about them. In this section we will look in detail at what “reference” means in Java. We will also
introduce box and arrow diagrams that may find helpful in understanding how they work, particularly
in more complex data.
In prerequisite units and in the previous sections you have declared an object reference variable and
create a class instance using a simple statement such as:
Age a = new Age();
Here we have used a class called Age and its default constructor to create a reference variable called a
and a new object using the Age class. We will now look at exactly what this means in the Java run-time
environment and look at how subsequent program operations affect such objects.
Before we look at objects we should consider the behaviour of the Java primitive types. A primitive
type is a data type used to declare variables as int, float, double, etc. A primitive type is also known
as a value type or built-in type in other languages. Such variables in Java result in memory locations
CSC72002 Study Guide Classes, objects and inheritance
1-7
being reserved to contain data of these types. We can think of such variables diagrammatically as in
Figure 1.1 where an int and a double variable called i and d respectively are declared.
int i=23;
double d = 4.321;

23
4.321

i d
Figure 1.1 – diagram of two primitive type variables
This diagram shows as a box the area of memory allocated for each variable. It is not important where
this area is in your program, but we will see below that sometimes this area is inside other objects.
Space for the value type variables is reserved directly in the computer memory and when we access
these variables the value is retrieved directly. The meaning of ‘directly’ becomes important when we
consider a non-value type variable, that is reference variables that are used to access an object. Now
examine Figure 1.2 which shows a declaration of one object of the Age class. We have deliberately
separated the declaration of the variable and the creation of the object to show the sequence of events.
Age a;
Age a;
a = new Age();
a null
a
Figure 1.2 – creating a non-primitive object
Notice how there is two areas of memory used in the declaration of the Age object instance. The variable
a contains a pointer (reference) to the data representing the Age object which is represented as an arrow.
This area is allocated from the system memory when the new Age() operation is called. The arrow
represents the idea of a pointer and is implemented in the system by placing a memory address (of the
Age object) in the variable a. This creates subtle differences between primitive objects and nonprimitive objects in the Java language that can be understood by diagrams like the one above.
Also in Figure 1.2 we have shown that a reference variable is initialise to a null value when a reference
variable is created. The value null represents an uninitialised reference variable and we will frequently
need to check for this value before accessing objects.
We have said so far that the unnamed box in Figure 1.2 represents instance of the Age object. The fact
that it has no name is important. It means we cannot access the object directly in the program, instead
we must access it through a reference such as the variable a. The familiar ‘.’ operator does this
automatically as we shall see below.
As a final elaboration of the diagrams above, we will show data attributes as part of the object. Consider
the following declaration of the Age class:
class Age
private int age;
public void setAge(int a) age = a;
public int getAge() return a;

YOU MAY ALSO READ ...  Questions Need Answers

This declaration has one primitive integer data attribute called age declared in the class. Figure 1.3
shows the creation of an Age object and initialisation of the internal attribute to the value 12.
Age a = new Age();
a.setAge(12);
a
age

12

Figure 1.3 – data attributes in object diagrams
CSC72002 Study Guide Classes, objects and inheritance
1-8
In this diagram we have labelled the data attribute in the Age object which represents the private data
field called age in that object. We will only do this in future when necessary. We have also shown
other ‘space’ in the Age object without labelling it. This other space may not always be shown in
future diagrams as it represents system data that is not important for our programming. However, we
will explain some of the contents of the extra data space in this and following topics.
The following activity gives you some practice with the diagrams above. The subtle problems that
arise with the object references will be shown using these diagrams so make sure you understand them
before progressing.
Activity 1-3: Java API abstract classes and interfaces
Read the textbook Section 9.5.1-9.5.3 (pp. 352-353). Draw diagrams like the ones in Figures 1.1
to 1.3 showing the state of program memory for after following C# code segments:
1. int x = 23;
int y = -3;
x = y;
2. Age a1 = new Age(); // Age class declared previously
a1.setAge(100);
Age a2 = new Age();
a2.setAge(18);
3. Age a1 = new Age(); // Age class declared previously
a1.setAge(100);
Age a2 = new Age();
a2.setAge(18);
a1 = a2;
The part 3 of the Activity 1-3 gives a clue to what we need to discuss next in this section. Consider the
following code which is like the third activity above:
Age a1 = new Age();
a1.setAge(100);
Age a2 = new Age();
Figure 1.4 shows the memory state after this code segment.
Age a1 = new Age();
a1.setAge(100);
Age a2 = new Age();
a1

100

a2
Figure 1.4 – two references to two objects
Now consider what happens when we then execute the next assignment statement:
a2 = a1;
This statement changes the pointer in variable a2 to point to the same object as a1. This is demonstrated
in Figure 1.5.
CSC72002 Study Guide Classes, objects and inheritance
1-9
Age a1 = new Age();
a1.setAge(100);
Age a2 = new Age();
a2 = a1;
a1

100

a2
Figure 1.5 – two references to same object.
Notice how we now have two pointers to the one object. It is the same object for both variables a1 and
a2. That means our code will access the same data. For example, if we now execute the following
code:
a1.setAge(23);
Console.WriteLine(“age a1=0”,a1.getAge());
Console.WriteLine(“age a2=0”,a2.getAge());
Then the following will be printed on the console:
age a1=23
age a2=23
There is a second attribute of pointers and objects that is shown in Figure 1.5. Notice how the object
created when the variable a2 is first initialised now has no pointers to it at all. Since it also has no
names to access it there is no way for the program to ever access it again. This object is technically
known as garbage in programming languages such as Java. Luckily for us, the Java language run-time
system has a garbage collector which periodically examines the program’s memory area and removes
all garbage so that the memory may be used for new objects. This means we do not have to worry about
garbage at all when writing programs because the garbage collector invisibly operates in the background
of a program. This is not the case in older languages such as C or early versions of C++ where it is
common for programs to run out of memory since they do not have an automatic garbage collector and
it is up to the programmer to remember to explicitly free the garbage objects. A common bug in such
languages is that the number of garbage objects grows until there is no memory left for the program.
Program bugs in those languages are also known as a memory leak. We will not have to worry about
garbage (or memory leaks) in this unit.
Activity 1-4:
1. Suppose we define a class called Room and declare variables as follows:
Room kitchen = new Room();
Room bedroom = new Room();
Room lounge = new Room();
Draw a diagram similar to the ones above to show what would happen if we executed the
following statements:
kitchen = bedroom;
bedroom = kitchen;
2. What if the following statements were executed instead of those in 1.
kitchen = bedroom;
bedroom = new Room();
CSC72002 Study Guide Classes, objects and inheritance
1-10
3. Going back to the Age class from the notes above, what is the output from the following
program? (use diagrams if you cannot visualize this in your head)
Age a1 = new Age();
Age a2 = new Age();
a1.setAge(18);
a2.setAge(100);
a1 = a2;
a2 = new Age();
a2.setAge(23);
Console.WriteLine(“age a1=0”,a1.getAge());
Console.WriteLine(“age a2=0”,a2.getAge());
The simple program segments above actually produce very simple memory configurations. More
complicated data structures will have to be represented by much more complicated diagrams. For
example, an array of objects will have separate objects for the array and each of the elements of the
array.
As an example, consider the array of Shoe objects created using the following Java code.
Shoe [] bagoshoes = new Shoe[5];
bagoshoes[0] = new Shoe();
bagoshoes[1] = new Shoe();
bagoshoes[2] = new Shoe();
bagoshoes[3] = new Shoe();
bagoshoes[4] = new Shoe();
After execution of this code we can draw a memory diagram as shown in Figure 1.6.
Figure 1.6 – Array of five Shoe objects
Notice how references to the array elements are embedded in the array object. These are loaded with a
reference when each of the new statements is executed. Note also that we never initialised the attributes
of the elements in the array in this example.
We can extend the diagrams introduced in this section to demonstrate much more complicated code.
CSC72002 Study Guide Classes, objects and inheritance
1-11
Activity 1-5:
Figure 1.6 shows an array fully initialised. Draw the three stages of building this data structure
separately. The stages are labelled in the following code:
// stage 1
Shoe [] bagoshoes;
// stage 2
bagoshoes = new Shoe[5];
// stage 3
bagoshoes[0] = new Shoe();
bagoshoes[1] = new Shoe();
bagoshoes[2] = new Shoe();
bagoshoes[3] = new Shoe();
bagoshoes[4] = new Shoe();
Refer to your previous notes on arrays if you wish to revise arrays.
Next, we look at inheritance.
Inheritance
Inheritance is one of the important features of most object-oriented languages (but not all). You have
already learned about simple inheritance and that is what we will revise here. However, inheritance
gets more complicated and the next few topics will look at how more complicated structures have
evolved to allow more comprehensive inheritance hierarchies to be developed.
Inheritance is all about re-use of code. The idea is that encapsulated code can be developed, specifically
for you or other programmers to re-use in the same project or in other projects. For example, the Java
developers have provided hundreds of classes containing code for re-use. This is called the Java API.
That code is structured as a collection of classes in a very complex inheritance hierarchy. For you to
use it effectively, you must understand the basics of inheritance.
The first thing to revise is the terminology. Inheritance is implemented using the extends keyword
with statements such as:
class A extends B …
While we can say that A ‘extends’ B, you will also come across alternate descriptors. Terminology in
inheritance is not straight forward as different authors and different languages use different words for
the same concept. Table 1.1 shows several terms for the basic inheritance concept that you will come
across that mean the same thing. You will see that the textbook uses the first two terms mainly, but
does occasional use the other terms.
A class that is used for inheritance
(right hand side of ‘extends’)
The resultant class after inheritance
(left hand side of ‘extends’)

YOU MAY ALSO READ ...  decision making.
superclass
parent class
base class
subclass
child class
derived class

Table 1.1 – inheritance terminology
Using the terms superclass and subclass may be counter-intuitive so be careful when you read or use
them. Usually the prefix ‘super-’ usually means bigger or expanded. It’s the subclass that is the bigger
class because it adds to the superclass.
The idea of inheritance and the Java implementation of inheritance may become clearer if we show a
simple example. We will start with a class called Person designed to represent a human person. For
simplicity, we will only save the person’s name as data. We can declare such a class as follows.
CSC72002 Study Guide Classes, objects and inheritance
1-12
public class Person

private String name = “”;
public void setName(String n) name = n;
public String getName() return name;

Now there are all sorts of people. Suppose we would like our program to identify students, who are the
author’s favourite type of person. We would like to re-use the code for person but also add additional
information. For simplicity we will just keep a number representing a student identifier. A method for
printing out the student details will also be useful. We can declare a class called Student as follows.
public class Student extends Person

private int ID;
public void setID(int id) ID = id;
public int getID() return ID;
public void print()
System.out.println(“Student name: ”+getName()+”, ID: “, ID);

Notice how we have called the getName() method from the Person base class from inside the derived
class. We can do this because getName() was declared as a public method. We also called it as if it
was a member function of the Student class. As another example examine closely the following code
sequence:
Student stud = new Student();
stud.setName(“Joe Blow”);
stud.setID(1234567);
stud.print();
Now the setName() method used here is not declared in the Student class. However, it is still
available since it inherited from the Person base class, just as the getName() member function was.
It is worth noting that, if it were declared as a private member function in the Person class then it would
not be available. For the same reason, the name data field declared in the Person class cannot be
directly accessed from inside the student class, however we can indirectly access it as is done in the
print() member function by calling the public methods of Person.
The following activity will ask you to look at another example in your textbook.

 Activity 1-6: Inheritance
Read the textbook Section 11.1 and 11.2 (pp. 432-438).
1. Implement the above Student class and the mainline code and observe the output.
2. Implement a class definition for Staff which will contain a string attribute for room
number and will use Person as a base class. Test it by printing out the contents of the
Staff objects created in the mainline. (You will need to have getter methods
implemented in the Staff class to retrieve the values).
3. (optional) Implement the circle/rectangle examples from the textbook. This is a lot of
coding but is an additional exercise.

CSC72002 Study Guide Classes, objects and inheritance
1-13
Inheritance in UML Class Diagrams
UML class diagrams can be used to show diagrammatically the inheritance relationship. It is done by
using an open arrow to connect two class diagrams, the base class and the derived class. The arrow
always points to the base class.
For example, Figure 1.7 shows the simple classes from the previous section and their inheritance
relationship.
Figure 1.7 – inheritance in UML class diagrams
Notice that the inherited methods are not repeated in the derived class. When reading these diagrams,
you must deduce the inherited field and members by following the inheritance arrow. The following
activity shows another example.

 Activity 1-7:
In Activity 1.6 you were asked to design a class for staff members. Add to the above class diagram
to add the Staff class. Can you see alternate ways to draw the arrows?

Next, we look at the super keyword.
The super keyword
Simple inheritance introduces two new problems that need solutions so inheritance works nicely:
1. What do we do with the constructors defined in a super class?
2. How do we call member functions in the super class?
Both these are solved with the super keyword. We will demonstrate the problems by redefining the
previous Person and Student classes. Suppose we redefine the person class as follows:
public class Person
private String name;
Person(String n)
name = n;

public String getName()
return name;

public void setName(String n)
name = n;
CSC72002 Study Guide Classes, objects and inheritance
1-14

public void print()
System.out.print(“name: “+name);

This version of the Person class is perfectly valid but introduces two specific problems. The first is how
can we use the constructor in the subclasses? The second is, how do we access the print() method if
we have one with the same name in the subclass? You will recall from your prerequisite units that this
is called overriding a method.
The answers to both these questions are provided by the follow version of the Student class.
public class Student extends Person
private int ID;
Student(String n, int id)
super(n);
ID = id;

public int getID()
return ID;

public void setID(int id)
ID = id;

@Override
public void print()
super.print();
System.out.println(“, ID: “+ID);

You can see here that we call the superclass constructor using the super keyword as the name of the
constructor. We also access the superclass version of the print() method using the super keyword
to specify the name of the class it is defined in (the superclass).
You may be wondering what happens if we do not specify a super class constructor in our subclass
constructor. The answer is that java always calls the default constructor (the one with no parameters)
of the superclass if no super() call is coded. That also means that you must have a default constructor
in your superclass for these occasions. Recall that if you define a constructor then the automatic default
constructor is no longer available so you will need to code a default constructor, i.e. one with no
parameters.
The above example also demonstrates the use of the @Override directive which is used to signal that
a method in the super class is being overridden in the subclass. You will have learned in your
prerequisite units that we can redefine an inherited method by overriding it. It is also important not to
confuse the concepts of overriding with overloading. An overloaded method is a method that has the
same method name but can be distinguished from the other method by having different parameter
numbers or types. An overridden method has the same number of parameters and each has the same
type as the overridden method.
CSC72002 Study Guide Classes, objects and inheritance
1-15
Activity 1-8:
Read the textbook sections 11.3, 11.3.1 to 11.3.3 (pp. 438-440).
1. Implement the above code using the two classes with the two super keywords in the
derived class.
2. Implement a class for Staff objects as you seen previously. This version should have a
constructor with the staff member’s name and room number. It should also have an
overridden version of the print() method.
Next, we look at polymorphism.
Polymorphism
Polymorphism is one of the distinctive attributes of object-oriented programming languages. It adds to
the re-use provided by inheritance to allow the same code to be designed to process many different
(though related) objects. In this topic we will extend our knowledge of classes to see how polymorphism
works. We will start our discussion of polymorphism by studying the system class Object and see
how it may be used in a polymorphic way. We will then look at polymorphism in a more general way.
The Object class
The Java language automatically includes a special class called Object. It is a special class because it
is the base class for all declared classes that do not specify a base class. If you think about that for a
while you will realise that the Object class is the base class of any inheritance hierarchy.
So for example, suppose we declare the following simple version of the Person class we used
previously which will contain just a string for a person’s name.
class Person

private String name;
public Person(String n) name = n;
public string getName() return name;

This is equivalent to the class header:
class Person extends Object

private string name;
public Person(string n) name = n;
public string GetName() return name;

So if Object is the base class of all classes either directly or indirectly through inheritance hierarchies,
the Object class it can contain some methods that will be available in all classes via the inheritance
mechanism. You will discover the complete list of methods in the activity below. We will just discuss
three of them here.
A useful method inherited from the Object class is toString(). This method prints out the object’s
class name, including its namespace. So the following code sequence using the above definition of
Person class will access the inherited ToString() method.
class Persons
public static void main(String[] args)

YOU MAY ALSO READ ...  Discuss the relationship between Early Cognitive Behavioral Therapy in Autistic Children and Success in Adulthood

Person p = new Person(“Barry”);
System.out.println(p.toString());

CSC72002 Study Guide Classes, objects and inheritance
1-16

This will print a line similar to the following on the console:
[email protected]
This represents the package persons, the class Person, and the hash code for the object following the
‘@’ symbol. While this information is not normally useful except for debugging purposes, we can
always override this method in out classes to provide more useful information.
The Java compiler is aware of the toString() function because it is inherited by all objects from the
Object class. It can automatically convert any object into a string by calling the toString() member
function. For example, the println() function call above can be replaced by the following code which
causes the compiler to automatically call the toString() member function printing the same line of
text.
System.out.println(p);
You will recall from your previous study that you can redefine the toString() method in subclasses.
So for instance, we could redefine the toString() method in the above Person class to print out the
class name and the value by inserting the following method definition in the Person class.
@Override
public String toString()

return “person with name ” + name;

Execution of the TestObject program would then print out the following message on the console
instead of the default message:
person with name Barry
The second useful method inherited by all classes is the equals() method which can be used to check
if two objects are equivalent. The full signature of the method is:
public boolean equals(Object o)
Now the inherited implementation checks that the two objects are actually the same object in memory.
To demonstrate this method, the following code creates three variables (references) and two objects of
type Person. It then uses the Equals() method to check if the first method is the same as the second
and the third.
Person p = new Person(“Barry”);
Person p2 = new Person(“other”);
Person p3 = p;
if (p.equals(p2))
Console.WriteLine(“p and p2 are the same object”);
if (p.equals(p3))
Console.WriteLine(“p and p3 are the same object”);
When we execute this code only one line will be printed:
p and p3 are the same object
Make sure you understand why this is true. The diagrams box and arrow diagrams introduced at the
beginning of this topic may help you understand this if you are not clear.
Although the inherited equals() methods check that the objects being compared are the same object
in memory, this does not have to be the case. The equals() method can be overridden just like to
toString() method so we can implement our own equality method. However, this is complicated by
some technical implementation requirements that will mean we will not give an example.
There are several other methods inherited by all classes from the Object class. We will come across
some of these in the Topic on parallel programming. Others you may come across in code examples on
the internet but in general they will require understanding of low level technical details that we are not
concerned with in this unit.
The following activity will let you see the other methods of the Object class. You will see that they
are interrelated to a certain extent.
CSC72002 Study Guide Classes, objects and inheritance
1-17
Activity 1-9:
Read Section 11.6 of textbook (p. 444).
1. Implement the above Person class without the overridden toString() method to
check the output of the println(p) method call.
2. Implement the above overridden toString() method in the person class and re-run the
program to observe the new format.
Examine the full list of member functions of the Object class in the Java 8 API documentation:
https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
Now that we have introduced the Object class we will use it to show how polymorphism works.
Polymorphism with Object
In this section we will discuss the idea of polymorphism in object-oriented languages and how it
increases code re-use. We will do this by examining an example method that illustrates the concept.
Polymorphism is about using methods of a base class to process objects of a class derived from the base
class. Remember that objects of derived classes inherit methods and attributes, can redefine them, but
cannot remove them so they will always be present in objects of derived classes. Carefully look at the
following method definition.
public void printString(Object o)

System.out.println(o);

This method will happily take a reference to any program object as an argument! Java allows variables
(a parameter variable in this case) declared with a class to hold references to any object of derived
classes. This makes sense because all objects of derived classes will also have inherited all the
superclass attributes and member functions. Now, since the Object class is the base class of all class
hierarchies, this method will be able to take any object reference as a parameter. That in turn implies
that the printString(o) function call will always be able to call the toString() member function
inherited from the Object class for any object passed as parameter.
Suppose we have a simple class called Person defined as follows.
class Person

private String name;
public Person(String n)

name = n;

public string getName()

return name;

Now suppose we have the following code sequence which calls the PrintString() method as
follows.
Person p = new Person(“Barry”);
printString(p);
Then a message like the following would be printed on the console (assuming the Person class is
declared in the testPoly package).
[email protected]
CSC72002 Study Guide Classes, objects and inheritance
1-18
You should recognize this as the default value printed for an object given to the System.out.print()
function discussed in the previous section.

 Activity 1-9:
Read Section 11.7 of textbook (p. 445).
1. Implement the above printString() method to test the polymorphism.
2. Override the toString() method in the Person class as was done in the previous
section. Run the program again to see what is printed in the console. We will see how
this works in the following section.

Next, we look at more general polymorphism.
Polymorphism in general
We have used the Object class to demonstrate polymorphism in Java. Although this is possible, it is
not the major use of the concept. Re-use enhancements by polymorphism are much more specialised
class hierarchies. We will demonstrate a simple case by deriving a class hierarchy shown in Figure 1.8
(this is also the answer to activity 1.7)
Figure 1.8 – extended class hierarchy
Now in the same way we used the Object class for polymorphic processing, we can use the Person
class to declare variables to process Student and Staff objects, and any other class derived from the
Person base class.
For example, we could declare the following method for printing the name stored in the name field for
object of class Person, Student or StaffMember.
public static void printName(Person p)

System.out.println(p.getName());

Then we could print the names of various objects as follows.
Person p = new Person(“Barry”);
Student s1 = new Student(“Jo”, 1234);
Staff st1 = new Staff(“Chris”, “MG103”);
printName(p);
printName(s1);
printName(st1);
Notice how we have used one implementation of a method to print any of the three object types. This
is re-using the printName() member function for several different objects, which happen to have a
common inheritance ancestor.
You may have already noticed that a potential problem exists here. What if the method called in the
base class is overridden in the derived class. For example, what if the Student class in the above
CSC72002 Study Guide Classes, objects and inheritance
1-19
example overrides the getName() method, which is perfectly legal in Java. We would then have a
version of the method in both the base class and the derived class. The answer is that Java performs
dynamic binding. This means that the language decides which method is appropriate at run-time so if
the Student class did redefine the inherited getName() method then its version of the getName()
method would be called.

 Activity 1-10:
Read Section 11.8 in the Textbook (pp. 446-449).
1. Either use your previous implementation or re-implement the Person, Student & staff classes
above. Then implement the printName() method as shown. Verify that the program
compiles and runs with calls to the method using three different object classes.
2. Override the getName() method in the Staff class to return a different string, say “Mr
XXXX” where XXXX is the name attribute. Re-run the program to observe how dynamic
binding selects the new method when an object of type Staff is passed as a parameter (but
not for other parameter types).

In the next topic we will see how polymorphism results in further extensions to the syntax of class
declaration, specifically abstract classes.
Summary
In this Topic we have revised several concepts that you have already learned about in previous units.
The terminology used may be different but the concepts were previously taught. We looked at the
structure of normal classes, which are composed of attributes, constructors and methods. We introduced
box and arrow diagrams that may help you understand how objects and object references are
implemented in the Java runtime. We also looked at basic inheritance, revised the UML diagrams for
inheritance and noted how the super keyword can be used to improve the flexibility of Java inheritance
syntax. Finally, we looked at polymorphism using the Object class and more general forms of
polymorphism using our own classes. We noted how dynamic binding allow the correct method to be
selected by the Java run-time system.
CSC72002 Study Guide Classes, objects and inheritance
1-20
Answers to Activities
Most of the activities require code. However, the ones that require written actions have sample
answers below.
Activity 1-3:
1. This code overwrites x with the value in y.
2. This code overwrites the reference without modifying the objects.
3. In this one we create a garbage object when the reference from a1 to the first Age object is
overwritten by a reference to the second Age object.
CSC72002 Study Guide Classes, objects and inheritance
1-21
Activity 1-4:
1. After the statements below the memory looks like:
Note that the final statement actually does not change anything since it overwrites the point to the
second object with the same pointer. Note also we have created one garbage object.
2. The following diagram shows the memory state after the statements below.
Notice how we now have four objects, one of which is garbage.
3. The output from the program would be:
age a1=100
age a2=23
If you drew a diagram then it would be very similar to the one for part 2 without the den object.
CSC72002 Study Guide Classes, objects and inheritance
1-22
Activity 1-5:
Stage 1: create the variable
Stage 2: create the array object
Stage 3: create individual elements in the array
Activity 1-7:
Two styles are as shown:
Either of these versions is reasonable when you draw your diagrams. Some drawing packages make it
hard to do the style shown on the left-hand side.

CLICK HERE TO GET A PROFESSIONAL WRITER TO WORK ON THIS PAPER AND OTHER SIMILAR PAPERS

CLICK THE BUTTON TO MAKE YOUR ORDER

YOU MAY ALSO READ ...  We can help on: Why would the Doctrine of Double effect not necessarily bar the eating of meat?