Vous êtes sur la page 1sur 55

Chapter 6.

Java Classes & Objects

Context

The purpose of this unit is to clarify and extend the concepts of object orientation as
they apply to Java programs. You will already have come across the basic concepts of
'class', 'object', 'variable' and 'method'; this unit gives more details and explains how
new classes are implemented.

Objectives

At the end of this unit you should be able to:

 Write simple Java applets that define and use methods and variables
 Explain the difference between public and private variables and methods
 Explain the difference between class and instance variables and methods
 Understand the scope of class, instance and local variables
 Be able to write programs that make use of classes in packages

Study Planning

You should expect to spend approximately 9 hours studying this unit. You may find it
convenient to break up your study as follows:

Disk-based Content: 2¼ hours


Application: 3 hours
Set textbook Content: 1 hour
Reflection (On-line discussions, review 1 hour
questions):
Tutorial Work: 1 hour
Related Coursework: ¼ hour
Extension Work: ½ hour

Equipment/software required

 Sun Java 2 Platform (also known as Java Development Kit 1.3)


 TextPad 4.5
 A Web browser

Reading material & resourses

Core texts (supplied with module material):

1. Java: how to program. H. M. Deitel and P. J. Deitel, 3rd edition, Prentice-Hall, ISBN: 0-
13-012507-5

Online Resources:

1. Frequently-asked questions
2. Additional Source Code Examples
Introduction to unit 6

In this unit we return to the object concepts introduced at the beginning of the module.
We are now able to consider the detailed aspects of the implementation of classes with
methods and variables based on the programming concepts and skills covered in the
units up to this one.

In fact you have already been working with the implementation of several Java object
concepts, in the process of creating applets (and some applications) for investigating
and solving problems with such programming features as iteration statements and
strings.

It is worth keeping in mind that with object orientation there is a stark contrast between
the complexity of the theory and the simplicity of the practice.

Object technology is a relatively new field, and therefore it is changing very rapidly. This
means that different people, textbooks and Web sites use different terms for the same
thing. In this module we have tried to be consistent in the use of terminology, but our
use of terminology is not necessarily compatible with anyone else.

Unit 6 — Assigned reading

Java: how to program. H. M. Deitel and P.J. Deitel, 3rd edition,


Prentice-Hall,ISBN: 0-13-012507-5 sections 8.1-8.4, .6-8.9, 8.15-8,16
pp 324-336, 340-354, 367-373 respectively from Chapter 8

Classes and Objects

Classes in modelling and programming

It is important to realize that classes have two related meanings in software


development. First, a class is a modelling construct, that is, a way of representing
entities in the real world. In the `analysis' stage of software development, the developer
may build a model of the system to be developed based on classes. Classes are also
programming constructs, that is, units of organization of a program. Ideally there should
be a strong correspondence between these two views: classes in the model should
correspond to classes in the program. In practice the correspondence is rarely one-to-
one; the programmer will usually have to introduce additional classes to support the
operation of the program at the technical level. The Java `String' class is an example
of this use of a class.
In modelling, classes can be concrete or conceptual. A concrete class is one that
represents a physical object in the real world. Here are some examples:

A conceptual class is one that does not have a physical presence. Here are some
examples:

 a bank account
 a mortgage
 a musical recording
 a picture

Note the difference between a musical recording, which is conceptual, and a compact disk,
which is concrete. In everyday speech we happily mix these up. We may talk, for example, of
'playing Beethoven's fifth symphony' and not, 'playing the compact disk which embodies a
recording of Beethoven's fifth symphony'.

However, if you were designing software to catalogue a large music library, you would
have to ensure that the difference between these concepts was perfectly clear in your
mind. This concept is considered in more detail in the 'discussion' topics.

Exercise 1 — Examples of classes

Although there is a good correspondence between the use of classes for modelling and
the use of classes to organize a computer program, historically these uses of classes
have been developed by different people, and use different terminology. The Unified
Modelling Language (UML) has started to impose a standard terminology on the
modelling use of classes, but the use of classes in programming is still subject to a
variety of different terms. There is a summary of the terminology used in object
orientation at the end of this unit.

Defining a class in Java

The implementation of a class in Java always looks similar to the following:

class Customer

// variables

<variable1>

<variable2>

<variable...>

// methods

<method1>

<method2>

<method...>

A class defines a set of variables (technical instance variables, or fields, or attributes)


and a set of methods. A class definition acts as a template for each instance of the
class created when a Java program runs. When a Java program runs none, one or
many instances (objects) may be created from a single class.

Classes are central to a Java program. Every program must have at least one. The
program may use classes to represent real world (concrete) categories of object, or the
program classes may be entirely internal (such as user interface classes like Button,
MenuItem etc.) Program instructions can only exist inside methods, which are inside
classes.

The program designer decides what variables and methods to define as part of a class
after analysis and modelling activities, prior to coding at a computer.

Declaring variables before methods


In fact it is only a convention that a class's variables are defined before its methods —
the Java compiler does not mind if they are mixed up.

Why are classes important?

In Java, classes are the main organizational unit of a program. By their very nature
classes tend to be self-contained. This leads to easier management of large projects,
and easier maintenance of the software. You should spend some time thinking about
these issues at the end of this unit (there is a question to that effect in the `reflection'
section).

Variables

Variables store values. Variables have a name, a type, and a value.

For example, in a program concerned with company accounts, we may define a class
called Customer, representing and managing the details of the company's customers.
Variables of Customer may include name, address, credit limit, etc. Each object of class
customer may have different values of these variables.

Taking the 'Customer' example, let's assume that the important features of a customer
are name, address, account balance and credit limit. We might define this as below:

class Customer
{
// Variables of customer
String name;
String address;
int accountBalance;
int creditLimit;
// Methods of Customer go here
}

Defining a more complex Class

Considering a library records system, we shall define a class for text items as follows:

class TextItem
{
// variables
String title;
int numPages;
String shelfMark;
boolean onLoan;
int daysLate;

// methods
void TextItem( String itemTitle,int itemNumPages,
String itemShelfMark)
{ // method implementation }

String getTitle() { // method implementation


}

int getNumPages() { // method implementation


}

String getShelfMark() { // method implementation


}

boolean getLoanStatus() {// method implementation


}

void setLoanStatus(boolean newLoanStatus)


{ // method implementation
}

int getDaysLate() { // method implementation


}

void setDaysLate(int newDaysLate)


{//method imlementation
}

double getFine() { // method implementation


}

void informBorrowerOfFine( <args> )


{// method implementation
}

For now the implementation of the methods has been replaced with comments.

As can be seen from the class definition, the class defines 5 variables:

title
numPages
shelfMark
onLoan
daysLate
These correspond to attributes identified during analysis and modelling. However,
another attribute was also identified, which has not been implemented as a variable in
this class. That other attribute was the fine due on a TextItem object.

A general rule of thumb, when performance is not a major issue, is never to store a
value that can be calculated when it is needed. If we assume that the fine for a TextItem
is always 0.05 pounds for each day late, since we have the variable daysLate already
stored as a variable, we can always calculate the fine when needed.

A method that needs to find out the fine is the getFine() method, which we might
implement as follows:

double getFine()
{
return (0.05 * daysLate);
}
This method calculates the fine and returns the result of the calculation as a reply.

Implementation observation
Not every attribute identified in analysis and modelling is implemented as a variable.
If a value can be calculated form other variables, then a get() method is all that is
needed — the implemented variable will be set via changes to the variables that make
up its calculation.

This class of objects has behaviour. For example, the method


informBorrowerOfFine(<args>) may result in the retrieval of a borrower's
address, and a letter being sent to them, if the fine reaches a certain amount (say 5.00
pounds).

Creation and deletion of objects

The ‘new’ operator creates new objects of a specific class.

An object is an instance of a class. In Java we can create an object using the keyword
new as follows:

new String("Fred Smith");


new TextItem( "Deitel & Deitel", 1041, "Dei 304.167");
new BouncingBall();
Such statements will result in a new object being created — a new instance of the
specified class. When a new object is created, an area of the computer's memory is
allocated to store the object.
Objects do not usually have to be explicitly removed. A process called garbage
collection is how the Java run-time interpreter gets rid of them when they are no longer
accessible.

Examples of 'new’ statements

In the example below, 'aMenu' is the name of a particular object of class Menu. Note the
brackets after the name of the class; their significance is explained later this unit:

Menu aMenu = new Menu();


Consider the following statement:

new Applet();
a specific object (of class Applet) is created, but it never gets assigned to a variable.
This object must be entirely self-contained, as the method that creates it has no way of
communicating with it after creation.

Classes and Objects — Activities and Exercises

Exercise 2 — Classes and Objects Summary

Exercise 3 — Class definition

Constructor methods

The statement:

new TextItem( "Deitel & Deitel", 1041, "Dei 304.167");


might result in the following object being created in the computer's memory:

TextItem object

Variables title = "Deitel & Deitel"

numPages = 1041

shelfMark = "Dei 304.167"

onLoan = false
daysLate = 0

Notice that the onLoan status is false and the value of daysLate is zero, even thought
these values were not part of the statement. In fact, even though values like "Deitel
& Deitel" were part of the statement, how did they get into an object?

Statements that create objects are actually invoking methods called constructor
methods. Each class has a constructor method that executes when a new object is to
be created of that class. We might define a constructor method for our TextItem class
as follows:

void TextItem( String itemTitle,int itemNumPages,


String itemShelfMark )
{
// use method arguments to initialise variables
title = itemTitle;
numPages = itemNumPages;
shelfMark = itemShelfMark;

// set some default values for variables for new object


onLoan = false;
daysLate = 0;

}
As can be seen, for this constructor the arguments to the method (title, number of pages
and shelf mark) are used to initialise some of this new object's variables. In addition,
some variables (onLoan and daysLate) are automatically initialised to values
appropriate for a new object of the class.

A method is recognized as a constructor by having the same identifier (name) as the


class, e.g. TextItem.

All classes have constructor methods that state what should be done to create a new
object of the class. Sometimes constructors are not explicit in the definition of the class
(they may be inherited from another class — we'll look more at inheritance in the next
unit).

Constructors do not have to have arguments — for some classes of objects there is
some reasonable way create an object that does not need to have any initial values
provided.

Customer constructor example

The example below shows how to provide a class 'Customer' with a constructor.
class Customer
{
String name;
String address;
int accountBalance;
int creditLimit;

// Customer constructor
Customer ()
{
// Statements to initialize the object go here
}
}

Note that the constructor in this case is defined as Customer(), so to create a new
Customer object we would write:
new Customer();
Alternatively, let's suppose that when we create a new customer we will always specify
the customer's name, address, account balance and credit limit. In this case we would
define the constructor as follows:
// Customer constructor

Customer (String _name, String _address,


int _accountBalance,
int _creditLimit)
{
// set the variavbles of the class from
// the constructor's parameters

name = _name;
address = _address;
accountBalance = _accountBalance;
creditLimit = _creditLimit;
}
Then we might create a new Customer like this:
new Customer ("Fred Bloggs", "13 Acacia Avenue", 0, 2000);
Use of '_' prefix
Notice in the example above, rather than using a prefix like 'new' or 'item' for each
argument, the prefix '_' was used. This is another convention widely used to distinguish
between the names of arguments and the names of the variables they are setting. It is
important, whichever convention you adopt for the identifiers of arguments, that you do
not write methods that have either arguments or local variables that have the same
identifiers as your object's variables.

Arguments (parameters)
Arguments can be though of as the `input' to methods.

By `input' is meant an input from another part of the program, not from the user.
Arguments, like variables, have a name and a type.

Suppose that when a customer pays some money into an account, it increases the
account balance. We want to define a method called payIn() which is called whenever
the customer pays some money in. This method cannot add a fixed amount to the
balance, as it must be able to cope with any amount of money paid in. For example, we
would like to be able to write

payIn (300);
to pay in 300 pounds, and
payIn (10000);
to pay in 10,000 pounds, etc. The number in parentheses (brackets) is called an
argument of this method. We can define the payIn() method like this:
public void payIn (int amount)
{
accountBalance = accountBalance + amount;
}
Don't forget that accountBalance is the name of the variable that stores the account
balance for this customer.

Again, the name of the argument `amount' is only meaningful inside the method. We
could have used any name for this argument (provided all instances were the same)
and it would work the same. Of course, common sense suggests that you should
choose identifiers that make the program easier to understand.

Return value

The return value is the 'output' of a method in the same way that the arguments are the
'input'.

The return value is the result that a method sends back as a reply (to the message that
caused the method to be performed on an object). This is particularly important when
the purpose of the method is to allow other objects to find out something about this
object (i.e. get methods). The ‘something’ becomes the return value.

The return value of a method is the reply returned to the message statement that
invoked the method.. Writing data to the screen, to a window or to a file is not a return
value. The return value has a type, like a variable.

Continuing with the customer example again: suppose we need to calculate the interest
on a customer's account balance. Suppose further that we don't want to print this
interest, but use it in a later calculation. What we need here is a method that returns the
interest on the account. Then we can write something like:

double interest = calculateInterest();


// ... use the variable `interest' in another calculation
We might define the method calculateInterest()like this (note that for brevity I
had omitted the rest of the class definition; don't forget that this method is really inside
the class Customer.
public double calculateInterest ()
{
double newInterest = <interest_calculation>;
return newInterest;
}
Note that this method's definition starts public double, and not public void. It
returns a double value to the rest of the program. The actual value that is returned is
indicated by the statement
return newInterest;
Note that name of the variable newInterest inside the method
calculateInterest()only has a meaning inside that method. We could just as well
have written:
public double calculateInterest ()
{
double stupidName = <interest_calculation>;
return stupidName;
}
and this would not affect any other part of the program.

Novice programmers often become confused about the difference between `output' as a
return value, and `output' to, for example, the screen. For example, the operation
`println' is defined as having no return value (technically called a void return). But it
does produce an `output' to the display. Remember that a return value is an `output'
only to another part of the program, not to some other part of the computer.

Methods in general

Methods define what a class can do, or can have done to it. For example, a Mortgage
class may have the following methods:

 deduct payment
 calculate interest
 foreclose
 etc.
Note that it is not very clear which of these methods the class ‘does’, and which are
‘done to’ it (i.e. change the state of the object). This is often the case, and modern
practice is not to worry too much about this.

In Java, all program instructions must be inside methods. Methods can read and
change the values of instance variables as well as their own (local) variables.

Important points about methods include:

 Each method must have an identifier (name)


 Methods optionally have
 arguments (‘inputs’)
 a return value (‘output’) (see later this unit)
 Normally the only way that an object of one class can change the variables of
another is by invoking its access methods

Methods — customer example

Continuing with the Customer example: suppose we need the program to be able to
print each customer's account balance on the screen (perhaps using
System.out.println() or Graphics.drawString() ). A sensible place to put the
instructions for this is in a method called `printBalance' (for example). We might define
this method like this:

class Customer
{
String name;
String address;
int accountBalance;
int creditLimit;

// printBalance method
// prints the customer's balance

public void printBalance ()


{
System.out.println
("Current balance for "
+ name
+ " is "
+ accountBalance
+ " pounds");
}
}

In a specific object of this class, assume the customer's name is Fred Bloggs and the
account balance is 2,000 pounds, then executing this method would print:
Current balance for Fred Bloggs is 2000 pounds
Look carefully at the start of the definition of printBalance:
public void printBalance ()
The keyword `public' loosely means `can be called by methods outside this class'.
This concept is discussed in more later this unit.

The keyword `void' means that this method has no return value ('output'). The empty
parentheses (brackets) mean that the method has no arguments ('inputs').

It is often pointed the printBalance does have a form of output: it produces an


output on the screen. This confusion is the reason why we tend to use the term 'return
value' here rather that 'output'. When it is said that printBalance has no return value,
what is meant is that it would be meaningless to write a line like:

x = printBalance();

because nothing useful would be put into the variable x in this case. In other words,
there is no output in the form of a reply returned to the message statement that invoked
the method.

Methods — Activities and Exercises

Exercise 4 — Constructor Method

Exercise 5 — Methods Summary

Object variables — references to objects in memory

Although an object can be created using a very simple new statement such as:

new String("stock items");


except in certain cases this is not very helpful, since we have no idea where in the
computer this object has been created, and so it can never be referred to again by the
computer system.
When a reference is not needed
Sometimes there are actions defined in the constructor method of a class, that mean an
object once created and executing its constructor method can do whatever it is that we
want — without that object ever needing to be referred to again.

The new statement is actually an expression, which evaluates to a reference to the new
object.

Therefore it is very easy to store the reference in a variable. We can declare a variable
able to refer to an object of a certain class as follows:

<class> <variableIdentifier>;
For example:
String name1;
Ball ball1;
BankAccount customerAccount1;
At this point, these three variables do not refer to any objects (they have the value
null).

It is now possible to assign to such a variable the reference to a newly created object:

name1 = new String("Julie Brown");


ball1 = new Ball();
customerAccount1 = new BankAccout("Fred", "Smith", 304.02, "deposit");
Like arrays and primitive types of variable, it is possible to combine the declaration of a
variable, with the giving it an initial value. Thus:
String name1 = new String("Julie Brown");
Ball ball1 = new Ball();

both declare the variables name and ball1, and also make these variables refer to newly
created objects of the String and Ball classes respectively.

Variables can change

By their nature, a variable can change its value. A variable declared for referring to an
object of a certain class can refer to any objects of that class. So such a variable might
at one point be referring to one object, and at another point be referring to a different
object.

For example:

// object variable declaration

BankAccount accountToBalance;
...

accountToBalance = account1;

display( accountToBalance.getBalance() );

accountToBalance = account2;

display( accountToBalance.getBalance() );

So at one point during the execution of these statements, variable accountToBalance


was referring to the same object as account1, and in a later statement
accountToBalance was referring to a different object, the one referred to by account2.

This illustrates:

 a variable can refer to different objects at different times


 two (or more) variables can refer to the same object

Object individuality

Each object has individuality. So when a new object is created, it takes up its own part
of the computer's memory. The individuality of an object is not related to the values of
its variables (i.e. its state).

Consider the following statements:

LibrayItem book1;
LibrayItem book2;

book1 = new LibraryItem("Programming in Java", "J. Smith");


book2 = new LibraryItem("Java programming", "M. J. Jones" );

Two new objects have been created, which are instances of the class LibraryItem. The
first new object was created, and the variable book1 assigned the reference to its
location. The second new object was created in a different place in the computer's
memory, and the variable book2 assigned the reference to that object.

Now consider the following:

LibrayItem book3;
LibrayItem book4;

book3 = new LibraryItem("Program in C", "J. Smith");


book4 = new LibraryItem("Program in C", "J. Smith");

Just the same thing has happened as before — two different objects have been
created, and each one is stored in a different location in the computers memory.
Variable book3 refers to the first of these 2 new objects, and book4 refers to the second
of these new objects. Although both these objects have been created with the same
arguments (and so most likely have the same state) they are not the same object. It is
perfectly reasonable to consider that there might be two copies of the same book in a
library, but they are not the same objects.

Therefore, book3 does not have the same value (i.e. reference) as book4. Were we to
use the boolean test for equality:

(book 3 == book4)

this would result in an evaluation to false.

Local variables in methods

Different kinds of variable

What is intended by the term variable can become a little confusing sometimes, since
there are actually a number of different kinds of variable classes and objects can have.

The types of variables that exist are:

 instance variables
 class variables
 local variables (in methods)

Local variable

A local variable is one that can only be referred to inside a single method, or part of a
method. For example some local variables are local to a particular method, others are
local to only part of a method (such as in a compound loop statement).

An example of a local variable is the loop variable 'i' in this for loop:

for( int i = 0; i < 5; i++)


{
total = total + i;
g.drawString( total, x, y);
y = y + 20;
}
Since the variable 'i' is declared as part of this for loop, it cannot be referred to outside
the loop. So for example, if the loop were followed by a statement attempting to put the
value of 'i' on screen:
for( int i = 0; i < 5; i++)
{
total = total + i;
g.drawString( "total = " + total, x, y);
y = y + 20;
}

g.drawString( "i = " + i, x, y);

the following compilation error would occur:

The error says 'undefined variable i' since the compiler does not know what variable you
mean.

The part of a class where a variable can be referred to is called the scope of the
variable. An instance or class variable (see later this unit) has a scope comprising every
method of a class. A local variable may have a scope of a whole method, or may, as in
the loop above, have a scope of just one compound statement.

The full listing of our Scope class (without the offending line) is given below:

// Scope.java

// <APPLET code="Scope.class" width=275 height=200></APPLET>


import java.applet.Applet;
import java.awt.*;

public class Scope extends Applet


{
// instance variable
double average;

public void paint (Graphics g)


{
int x = 20;
int y = 20;

int total = 0;

for( int i = 0; i < 5; i++)


{
total = total + i;
g.drawString( "total = "
+ total, x, y)
y = y + 20;
}
g.drawString("Program terminating
", x, y);
}
}
There are 5 variables in this program:

 average
 x
 y
 total
 i

The variable average has a scope of all methods, since it is an instance variable.

The variables x and y and total have a scope of all the statements that occur after
them in the paint() method.

Variable i only has scope within the loop statement

The issue is scope is not covered in great detail here, however, be aware that an error
relating to an undefined variable is often one of either scope or a misspelling of the
variable identifier.

Access to methods and variables


Sending messages to use methods from other classes

Inside a class, unless specified otherwise, messages (usually corresponding to method


names) refer to the object of the class.

For an object to evoke some system behaviour not implemented as one of its methods,
it must send a message to another object (or invoke a class method — see later this
unit).

To send a message, both the receiving object and the message to send need to be
provided. This is achieved using the 'dot' notation, e.g.:

anObject.aMessage();
Every message must include an argument list in parentheses ( ... ), although there
may not be any arguments, so the parentheses may be empty: ().

The sending of a message to an object results in a method of that object being invoked.
invoked.

Keyword 'this'

When an object wishes to send itself a message to invoke one of its own methods, it is
not necessary to use the dot notation.

Consider an object that is an instance of the class Customer. A method of a instance of


this class might be invoked from the statement:

oldBalance = m1();
This statement means send the message m1() to itself, to result in its corresponding
m1() method being invoked.

In the absence of the dot notation Java assumes that a message is to be send to the
sending object itself.

Java actually provides a keyword to mean 'the object sending the message'. The
keyword is:

this
So we could replace the line above, with the following:
oldBalance = this.m1();
and the result would be the same. We have simply made it explicit that the message is
to be sent to the object itself.
In fact, when Java spots that no object (or class) has been specified to receive a
message, it inserts the sending object itself to be the recipient of the message (i.e. Java
will automatically insert the this. so that it know where every message is to be sent).

The this keyword is also useful when an object wishes to send a reference to itself as
part of a message or reply — in such a situation this is passed as a message
argument or a return value.

More about the 'dot' notation

Java uses the dot notation for the sending of messages to other objects (and methods).
For example, if a method in a different class wants to send a message to invoke the
method printBalance() for a particular object of class customer, we could write
(assuming the object is called aCustomer):

aCustomer.printBalance();
This means `send the message printBalance() to the object aCustomer'. This
would, had we defined the Customer class appropriately, result in the
printBalance() method being invoked for the object aCustomer.

The dot notation can also be used to send messages to receive values of variables
from objects. Thus the statement:

aCustomer.familyName;

is a message that will result in the aCustomer object returning the value of its
familyName variable (as long as this variable is public — see later this unit).

Access control

When a class of objects is defined, it is not the case that we wish all the methods or
variables of an object of the class to be available to other objects in the software
system. A general design rule for classes is that they should be self-contained, and
control access to its variables and methods

There is little point in creating careful get and set methods, if we do not prevent the
direct access of variables by other objects.

Java provides several of levels of access to the variables and methods defined in a
class. We shall investigate the access control provided by the following keywords:

 public
 private

You may, as an optional extension of your reading, wish to look into a third keyword
related to access:

 protected

Those variables and methods we wish to hide from other objects should be declared as
private. Those variables and methods we wish other objects to have access to should
be declared as public. For example, a MyCircle object may be defined as follows:
class MyCircle
{
// private variables
private int x;
private int y;
private int radius;
//... etc.

// public methods
public int getX(){ return x; }
public void setX( int newX ) {x = newX; }
//... etc.
}

This MyCircle class has only private variables, and only public methods — this
arrangement is quite common:
class MyCircle

Variables Methods

Private int x

Private int y

Private int radius

Public int getX()

Public void setX( int newX )


Since all the variables are private, this means another object cannot get access to them
directly. So in order for another object to create changes in a MyCircle object it must
send messages corresponding to the MyCircle object's public methods.

The protocol of an object is made up of its public methods.

The default is that, unless specified otherwise, a variable is not public.


Were a program to attempt to access a private variable, Java would respond that the
variable is not accessible. This is demonstrated by the applet below, which creates a
MyCircle object and then tries to send a message to retrieve the value of a private
variable (radius):

//AcessApplet.java
//<APPLET code = "AccessApplet.class" width=275 height=200></APPLET>

import java.applet.Applet;
import java.awt.*;

public class AccessApplet extends Applet


{

public void paint (Graphics g)


{
MyCircle circle1 = new MyCircle();
circle1.setX(20);
g.drawString("Circle X position is: " + circle1.getX(), 20, 20);
g.drawString("Circle1 radius is: " + circle.radius, 20, 20);
}
}

Note that classes themselves, as well as variable and methods, can have their access
defined. Thus a public class must be defined in a file with the same name as the
class, an is one that can be used by other instances of other classes. Classes can be
private, and only accessible to some other class defined in the same file.

Examples of class variables (and constants)


Classes with class constants provide constant (final) variables for reference. A good
example is the PI class constant of the Math class:

Math.PI;
g.drawString ("Math.PI =: " + Math.PI, 20, 20);

There is no need for any instance of the class to be created for some other other object
to be able to refer to this value. Notice that the dot notation is used for class variables
and constants, but with the class identifier rather than an object variable first. The
general form for referring to class constants and variables is as follows:

<classIdentifier>.<variable>
or if the class is within a package:
<package>.<classIdentifier>.<variable>
A class constant or variable is declared in the same way as an instance constant or
variable, except that the static keyword is included. So for example, a Client class might
declare a class variable to count the number of Client objects that have been created.
Such a variable would be declared as follows:
private static int numClients = 0;
Regardless of how many objects of the class existing, since this is a static variable,
this will be the only occurance of the variable numClients. Objects of the Client class
can update or read the variable, but since the variable is private, objects of other
classes will not be able to read or update this variable.

There are a number of situations where it is useful to have class variables, although
they are not that relevant to the programs you will be developing for this module. It is
are recommended you carefully study Deitel & Deitel to learn more about the use of the
static keyword to define class variables and constants.

Examples of class methods

In the same way that a class can provide variables and constants, a class can also
provide useful methods that do not require an object of the class.

An example of a class method used in previous units is:

nextGuess = Math.random();

This example is a method that returns a random value from 0.0 up to (but not including)
1.0. There is no need for an instance of the Math class for some other object to use this
public static method.
We could define a class method addUp() for a class Counter, that when provided with
an integer returns the total of numbers. For example, if provided with the number 3,
would return (1 + 2 + 3) = 6. Such a class and its public static method would look as
follows:

public class Counter

public static int addUp( int limit )

int total = 0;

int i = 1;

while( i <= limit)

total += i;

i = i + 1;

return total;

An applet to make use of this class method, without creating an instance of the class, is
as follows:

// <APPLET code="ClassMethodApplet.class" width=275


height=200></APPLET>

import java.applet.Applet;

import java.awt.*;

public class ClassMethodApplet extends Applet

public void paint (Graphics g)


{

int x = 20;

int y = 20;

// use Class method 'addUp()'

int result = Counter.addUp( 4 );

g.drawString("result = " + result, x, y);

Notice how there is never an instance of the class Counter created. The class method
is invoked through the sending of a message to the Counter class itself:

Counter.addUp( 4 )

Activity 1 — Geometric class constants

Activity 2 – Factorial class

Activity 3 – SavingsAccount class

Exercise 6 — DiceThrower

Packages and imports

In Java, it is usual for classes to be grouped into a package, i.e., a set of related
classes. A `packaged' class must be identified by its package name and class name, or
the 'import' instruction must be used to tell the compiler to look for classes in a particular
package.

You may have noticed at the start of many of the example programs a line like this:

import java.applet.Applet;
This is an indication that the program will make use of the class Applet which is in the
package java.applet.

The Java developers have designed the compiler to automatically import the standard
Java package java.lang. This defines important classes such as String. You will
need to refer to a Java reference, such as Deitel & Deitel or the on-line documentation
to identify what to import to use those classes that are not 'built-in' through automatic
importing.

You will also have seen the line

import java.awt.*;

This means 'search every class in the package java.awt'. When the compiler comes
across a class it does not recognise in the current program, it will see if it exists inside
the package java.awt.

Because an applet imports java.applet.Applet, then we can write the following


statement (secure in the knowledge the Java compiler knows where to find the Applet
class being extended):

class MyApplet extends Applet

If we did not use the import line, the program would still compile as long as I wrote

class MyApplet extends java.applet.Applet

If you are creating a large, sophisticated program, you may well want to group your
classes up into packages of related classes.

Packages and Imports — Activities and Exercises

Exercise 7 — Packages and Imports Summary

Summary of terminology

For reference, I have included a table comparing the terminology used in object-
oriented modelling and object-oriented programming. In the table below all the terms on
a given row are equivalent, or almost equivalent. The terms shown in bold are the
preferred terms for Java programming, as defined by the Java language specification
(available at http://java.sun.com/docs/books/jls/html/index.html)
object-oriented modelling Object-oriented programming

generalization/specialization inheritance

specializes extends

operation method, member function, function


member

attribute member variable, instance variable,


data member, field

virtual class Abstract class

object object, instance

event, message (nearest term is `method', but a


`method' and a `message' are not
strictly equivalent)

Activities

Activity 1 — Geometric class constants

(1) Create a class Shape which defines the following class constants:

numSidesSquare = 4

numSidesTriangle = 3;

numSidesPentagon = 5;
(2) Write an applet to test your class constants, that displays the following output on
screen:

Discussion/Suggested solution to Activity 1

Geometric class constants

(1) A solution for the class Shape is as follows:

class Shape

public static final int numSidesSquare = 4;

public static final int numSidesTriangle = 3;

public static final int numSidesPentagon = 5;

Note how each constant is:

public

since they are not much use if they are not readable by objects of other classes

Each constant is a `class constant' since it is defined as

static
Each constant is constant (i.e. an unchanging variable) because it is defined as:

final

(2) An applet to display these constants is as follows:

public class ClassConstantApplet extends Applet

public void paint (Graphics g)

int x = 20;

int y = 20;

int n1 = Shapes.numSidesTriangle;

int n2 = Shapes.numSidesSquare;

int n3 = Shapes.numSidesPentagon;

g.drawString("Triangle = " + n1, x, y);

g.drawString("Square = " + n2, x, y + 20 );

g.drawString("Pentagon = " + n3, x, y + 40);

Activity 2 – Factorial class

In an earlier unit you will have written a program to calculate the factorial of a number —
a model answer is Factorial1.java.

Modify this program so that it uses a class called Factorial to do the calculation. This
class should have a method called calculateFactorial() which contains the code to do
the calculation itself. In the program's main class, you should get the answer by
executing:

Factorial.calculateFactorial(50);
Discussion/Suggested solution to Activity 2

Factorial class

Check out the listings for classes:

Factorial2.java

// Factorial1.java
// A program that works out the factorial of 50, that is, 50 * 49 * 48.... * 2
* 1.
// This version implements an operation called factorial' that can get the
factorial
// of any specified number
// Kevin Boone, June 1999
import java.applet.Applet;
import java.awt.*;
public class Factorial2 extends Applet
{
public void paint (Graphics g)
{
g.drawString ("Factorial of 50 is...", 20, 20);
double result = factorial(50);
g.drawString (Double.toString(result), 20, 40);
}
// Here we define the `factorial' operation
public double factorial (int factorialRequired)
{
double result = 1;

for (int i = factorialRequired; i > 1; i++)


{
result = result * i;
}
return result;
}
}

Note, the calculateFactorial() method was made static because there is no reason
to need to create an instance of class Factorial in order to calculate a factorial.

Activity 3 — SavingsAccount class

Complete exercise 8.16 from Deitel and Deitel page 382.

Exercise 1 — Examples of classes


For each of the objects shown in the figure, think of computer applications that might
need to `know about' these objects. Try to think of at least two applications for each.

Discussion of Exercise 1

Examples of classes

Here are a few examples. You may well have come up with many more, and many
different examples;

Lightbulb

A system to control lightbulb production

Lighting system for use of stage

Traffic signal controller

Car

Control and monitory equipment in a car production plant

Recording and booking system for a car hire business

Control system for a taxi firm

Compact disk

Audio CD database

Control system for a CD production plant


Valve

Control equipment for any production plant that uses valves, e.g., chemical process

A stock control system for plumbing supplies

Exercise 2 — Classes and Objects Summary

Complete the following statements that summarise the concepts explored in the
'Classes' section of this unit:

Every program must have at least one _____.

A class acts as a ________ for a category of objects.

Program instructions can only exist inside _______, which are inside classes.

The ___ operator creates new objects of a specific class.

Objects are created and _________ during the execution of a program.

Classes do not usually have to be explicitly removed — the Java system gets rid of
them when they are no longer accessible. This is known as _______ __________.

_______ in classes can (and usually do) create new objects.

Discussion of Exercise 2

Classes and Objects Summary

Every program must have at least one class.

A class acts as a template for a category of objects.

Program instructions can only exist inside methods, which are inside classes.

The new operator creates new objects of a specific class.

Objects are created and destroyed during the execution of a program.

Classes do not usually have to be explicitly removed — the Java system gets rid of
them when they are no longer accessible. This is known as garbage collection.
Methods in classes can (and usually do) create new objects.

Exercise 3 — Class definition

Create a Java source file defining a Person class with the following variables and
methods:

Variables

age (a whole number)

height (a real number, such as 1.6 metres)

name (a piece of text, such as "Fred Jones")

Methods

`get' and `set' methods for the inspection and setting of the `height' variable

Discussion of Exercise 3

Class definition

The class overall needs to look as follows (remember, class names should start with a
capital letter):

class Person

// variables

// methods

Each variable needs to be declared with a type and identifier:

// variables

int age;

double height;

String name;
(remember, convention dictates that variables start with a lower case letter).

Each method needs to be defined by:

 return type
 identifier
 arguments
 statements to be performed

When a method does not return a value, its return type is the keyword void.

The 'set' method for the height variable will return no value (void), can have any valid
identifier, we shall call it setHeight following the convention to have a set method
named with "set" followed by the variable name, and will have one argument — the new
value of height. The action to perform is simply to assign the value of the argument to
the variable height:

// set height access method

void setHeight( double newHeight )

height = new Height;

(remember, except for constructor methods, methods are spelt with a lower case first
letter).

The 'get' method will return a value, since this is the role of 'get' methods. The type of
value returned will be that of the height variable. The identifier of the method follows the
convention of "get" followed by the variable identifier (i.e. getHeight). The method
requires no arguments, so there is an empty argument list between the parentheses '()'
— note that a method definition must have parentheses following the method identifier,
even when there are no arguments.

The action for the method is to return the value of the height variable:

// get height access method

double getHeight()

return height;

}
The whole class looks as follows:

class Person

// variables

int age;

double height;

String name;

// methods

// set height access method

void setHeight( double newHeight )

height = newHeight;

// get height access method

double getHeight()

return height;

Exercise 4 — Constructor method

Add to your Person class from Exercise 3 — Class definition a constructor that requires
arguments of age and name, and uses these arguments to set the initial values of these
variables.

Discussion of Exercise 4

Constructor method
The constructor method does not return a value (void), must have an identifier the same
as the class (i.e. Person), and has arguments of the new age and name. The actions to
be performed are to assign the values of the arguments to the variables for the new
object:

// constructor

void Person( int newAge, String newName )

age = newAge;

name = newName;

We have named the arguments appropriately since they will have the new values to be
assigned to the object's variables when created.

The whole class now looks as follows:

class Person

// variables

int age;

double height;

String name;

// methods

// constructor

void Person( int newAge, String newName )

age = newAge;

name = newName;

// set height access method

void setHeight( double newHeight )


{

height = newHeight;

// get height access method

double getHeight()

return height;

Exercise 5 — Methods Summary

Complete the following statements that summarise the concepts explored in the
'Packages and Imports' section of this unit:

A ___________ is a special method that is called automatically as soon as an


object is created.

The constructor method should __________ the object — by assigning sensible


values for its _________.

A constructor method is indicated by a method that has the same _________


(name) as the class.

A constructor is a ______, and may have _________ like other methods.

It is common practice to provide every class with a both a ___________ and a


toString() method.

Discussion of Exercise 5

Methods Summary

Suggested completed summary statements are as follows:

A constructor is a special method that is called automatically as soon as an object is


created.
The constructor method should initialise the object — by assigning sensible values for
its variables.

A constructor method is indicated by a method that has the same identifier (name) as
the class.

A constructor is a method, and may have arguments like other methods.

It is common practice to provide every class with a both a constructor and a toString()
method.

Exercise 6 — DiceThrower

Study the example program DiceThrower.

/*
DiceThrower.java

This applet simulates the rolling of a pair of dice. Whenever the user
clicks the mouse in the applet window, a number pair of numbers is
displayed. This display looks something like this:

(the image will only be visible if you are looking at the HTML version of
this program).

There are three classes making up this program. The main class, which is
a sub-type of applet, creates two objects of class `Die', of for each
Die to display. When the `paint' operation of the applet is called, it
in turn calls the `draw' operation in each of the Die object.

The third class is a sub-type of `MouseAdapter'. The use of this class


will be covered in more detail in the Unit of the Java user interface.
In brief, a MouseAdapter object can respond to user interactions like
mouse clicks. In this program, the MouseAdapter object simply calls the
operation `throwBothDice()' in the applet to cause a new pair of
numbers to be generated.

A not on English usage: one `die', two `dice'. The singuar form of `dice' is
`die'. So we define an object called `Die' (not Dice) as it is responsible
for drawing a single die. Sorry about this, but I didn't invent the
language.

Kevin Boone, July 1999


*/

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

/*
DiceThrower class
*/

public class DiceThrower extends Applet


{
/*
die1 and die2 are the two Die objects that will be displayed. These
objects are created in the `init' operation. die1 and die2 are
stored as attributes of this class
*/
Die die1;
Die die2;

/*
paint
As always, `paint' is called automatically whenever the display needs to
be updated. In this case the applet only paints the text message
`Click mouse anywhere to throw dice again'. The real painting is done
by the `draw' operation in the Die class
*/
public void paint (Graphics g)
{
die1.draw(g);
die2.draw(g);
g.drawString ("Click mouse anywhere", 55, 140);
g.drawString ("to throw dice again", 65, 160);
}

/*
init
init is called automatically when the Applet is initialized by the Web
browser
or applet viewer. In this case we create two Die objects. Their values are
stored as attributes of this class. We also create an object of class
DiceThrowerMouseListener which will detect when the user has clicked the
mouse on this applet.
*/
public void init()
{
die1 = new Die();
die2 = new Die();

/// QUESTION: what does `setTopLeftPosition' do, and why is it


/// important here?
die1.setTopLeftPosition(20, 20);
die2.setTopLeftPosition(150, 20);

// `throw' the dice so that they start off with random numbers
showing

throwBothDice();

// Create a DiceThrowerMouseListener object to handle mouse


// clicks. The `setDiceThrower' operation informs this
// DiceThrowerMouseListener object of the object that it
// must activate when a mouse click occurs (i.e., this applet).
// The keyword `this' simply means `this object here'

DiceThrowerMouseListener diceThrowerMouseListener =
new DiceThrowerMouseListener();
diceThrowerMouseListener.setDiceThrower(this);
addMouseListener(diceThrowerMouseListener);
}

/*
throwBothDice
This operation calls the `throw' operation in each die object and then
calls `repaint' to cause the display to be updated. In effect, repaint()
leads to `paint' being called
*/
public void throwBothDice()
{
die1.throwDie();
die2.throwDie();
repaint();
}
}

/*
Die class
The `Die' class is responsible for throwing the die (i.e., generating a
random
number between 1 and 6, and drawing the spots in the appropriate
places.

For simplicity I assume that there are only 7 possible places where a `spot'
can
be displayed, and I have numbered them from 0 to 6, as shown in the diagram
below:

0 1
2 3 4
5 6

So the number `1' is shown by drawing spot `3'. The number `2' is shown by
drawing spots `0' and `6'. The number `3' is spots `0', `3' and `6' and
so on.
*/
class Die
{
/* Attributes of the Die class */

/// QUESTION: are these attributes `public' or `private'?

int topLeftX;
int topLeftY;

// numberShowing is the number visible on the Die at any given time.


// `throwDie' operation sets this to a random number
int numberShowing = 6;

// The spot positions are specified as their X and Y co-ordinates.


// Spot `0' is at position (0, 0); spot `1' is at (60, 0) etc.
final int spotPositionsX[] = {0, 60, 0, 30, 60, 0, 60};
final int spotPositionsY[] = {0, 0, 30, 30, 30, 60, 60};

/// QUESTION: what does this operation do?


public void setTopLeftPosition(final int _topLeftX, final int _topLeftY)
{
topLeftX = _topLeftX;
topLeftY = _topLeftY;
}

/*
throwDie
Generates a new random number for the Die to display.
The random number is between 1 and 6
*/
public void throwDie()
{
/// QUESTION: why do we multiply by 6 and add 1?
// perhaps try a few other numbers and see what
// happens. You may need to look up what
// range of values Math.random() returns
numberShowing = (int)(Math.random() * 6 + 1);
}

/*
draw
Draw the spots on the die, according to the value stored in the
attribute `numberShowing'
*/
public void draw(Graphics g)
{
/// QUESTION: why do we pass `g' to each drawSpot
// operation, as well as the spot number?

switch(numberShowing)
{
case 1:
drawSpot(g, 3);
break;
case 2:
drawSpot(g, 0);
drawSpot(g, 6);
break;
case 3:
drawSpot(g, 0);
drawSpot(g, 3);
drawSpot(g, 6);
break;
case 4:
drawSpot(g, 0);
drawSpot(g, 1);
drawSpot(g, 5);
drawSpot(g, 6);
break;
case 5:
drawSpot(g, 0);
drawSpot(g, 1);
drawSpot(g, 3);
drawSpot(g, 5);
drawSpot(g, 6);
break;
case 6:
drawSpot(g, 0);
drawSpot(g, 1);
drawSpot(g, 2);
drawSpot(g, 4);
drawSpot(g, 5);
drawSpot(g, 6);
break;
}
}

/*
drawSpot
The drawSpot operation draws the specified spot. The numbering of the
spots is described above
*/

void drawSpot(Graphics g, final int spotNumber)


{
g.fillOval(topLeftX + spotPositionsX[spotNumber],
topLeftY + spotPositionsY[spotNumber], 20, 20);
}

/*
DiceThrowerMouseListener class
This class has an operation called `mouseClicked' that is called
automatically whenever the user clicks the mouse over the
object that this object is associated with. In the definition
of the main applet (above) we call `addMouseListener' to make
this association. These issues will be described in more detail
in a later unit of this course.
*/
class DiceThrowerMouseListener extends MouseAdapter
{
DiceThrower diceThrower;

public void mouseClicked (MouseEvent e)


{
diceThrower.throwBothDice();
}

public void setDiceThrower(DiceThrower _diceThrower)


{
diceThrower = _diceThrower;
}

There are a number of questions embedded in the comments in this code listing —
answer these questions.

Discussion of Exercise 6

DiceThrower

1. setTopLeftPosition is an method in class Die. It sets the position on the screen that
the die will appear. In this application, only the horizontal position needs to be set, since
both dice are at the same vertical position. However, it makes the class Die more
general if both horizontal and vertical positions can be set

2. The variables topLeftX and topLeftY are private to class Die. This is the default in
Java. To make them public would require that the public keyword be specified

3. setTopLeftPosition simply sets the values of the variables topLeftX and topLeftY.
These variables are used in the paint method to set the position where the spots will be
drawn

4. The method Math.random() returns a random number between 0 and 0.999999….


Multiplying this by 6 gives a random number between 0 and 5.999999…. Adding 1 gives
a random number between 1 and 6.9999999… When this is converted to an integer
(using int) the fractional part is discarded, given a random number between 1 and 6,
which is what is required for dice.

5. g is an object of class Graphics. This object contains the basic methods needed to
draw graphics. As this object is passed automatically to the paint method by the Java
system, it makes sense to pass it along to every method that does drawing. It is
possible to create a new Graphics object whenever required, but it is more efficient not
to.

Exercise 7 — Packages and Imports Summary

Complete the following statements that summarise the concepts explored in the 'Packages and Imports'
section of this unit:

It is usual for classes to be grouped into a _______, i.e., a set of related classes.

A packaged class must be identified explicitly by its _______ ____and _____ ____.

Alternatively the ______ instruction tells the compiler to look for classes in a particular
package.

The use of the asterisk '*' after a package name, rather than a specific class name,
instructs the compiled to ______________

_______________________.

Discussion of Exercise 7

Discussion of Exercise 7 — Packages and Imports Summary

Suggested completed summary statements are as follows:

It is usual for classes to be grouped into a package, i.e., a set of related classes.

A packaged class must be identified explicitly by its package name and class
name.

Alternatively the import instruction tells the compiler to look for classes in a particular
package.

The use of the asterisk '*' after a package name, rather than a specific class name,
instructs the compiled to search the package for classes it does not
recognise.

Review Questions
Review Question 1

In non-object oriented programming languages (like, C, Pascal, FORTRAN, etc.) the


basic unit of organization of a program is the function. A function is like a method, but
not in a class. In fact, programs in such languages can be thought of as one very large
class, containing all the methods of the program.

In what ways might the object-oriented strategy adopted by Java be superior to this? In
what ways might an object-oriented approach be a disadvantage?

Answer

Discussion of Review Question 1

Encapsulation is a very important concept in software engineering. If a computer


program exhibits encapsulation, this means that it is made up of independent, self-
contained parts.

Since there are strict rules about how classes can interact with one another, then a
program based on classes will tend to exhibit encapsulation. Good use of encapsulation
leads to the following advantages:

Reuse of program code

In activity 1 I asked you to think of computer applications that would need to know about
specific objects. Probably you were able to think of two or three different applications for
each object. However, in all likelihood the things they would need to know about each
class are likely to be similar. This is one of the great strengths of object orientation. By
focussing on the `real-world' features of the application, we encourage the selection of
components that can readily be re-used in new applications. As developing good quality
software is difficult and expensive, the ability to re-use it has to be an advantage.

Management of program complexity

A sophisticated piece of software may have millions of lines of program code. If you are
new to this subject (and as a student on this program you probably are), then you are
probably struggling at present with the detailed syntax of the Java programming
language. After a few months this becomes second nature, and you can begin to
struggle with the problem of managing and maintaining large programs. The class is a
natural way to group together those parts of a program that naturally belong together.
So in the class called BankAccount we would put all the program instructions concerned
with the management of bank accounts.

Easier fault-finding
If there is a fault in a program, the fact that classes are self-contained means that it is
relatively easy to decide which class is at fault.

Improved teamwork

The encapsulation of classes means that it is relatively straightforward for a number of


different people to work on the same program, by assigning them individual classes to
implement.

Discussion Topics

Discussion Topic 1 — Access methods

It is normal for a Java class to restrict access to its class and instance variables. For
example, if class X wants to get the value of a variable in class Y, it would normally call
a method (an accessor method) in class Y to do this.

Although it is possible to read an instance variable in a different object directly, like this:

int minutes = calendar.minutes;

We would normally use an accessor method, like this:

int minutes = calendar.get (Calendar.MINUTE);

Working this way leads to a slight increase in the complexity of every class, as accessor
methods need to be provided to control access to a number of variables.

So why is this way of working so widespread? What advantages does it have?

Contribution for Discussion Topic 1 — Access methods

Contribution for Discussion Topic 1 — Access methods

There are two important reasons, a philosophical one and a practical one.

Philosophically, an object of a class `owns' its instance variables, and can supply or
withhold details as it sees fit (or rather as its programmer sees fit). Similar examples
abound in real life. If I want to know a person's name I can either ask him, or grab his
wallet and look through it for his name on a credit card. Clearly the latter approach is
rather invasive, and would not normally be acceptable. Of course, if I ask a person his
name he could lie, and in the same way the Calendar object could respond to
get (Calendar.MINUTE);

with the wrong time.

Practically, if the only way to get access to the current number of minutes past the hour
is by calling the appropriate `get' operation, then it is very easy for the programmer to
control how that data is stored and used. Suppose, for example, that the Calendar class
stores its time internally as the number of seconds past midnight. In this case there is
no minutes variable; the class calculates it on demand from the number of seconds. If I
want to change the internal operation of Calendar, provided other classes get access to
it by its `get' methods, there is no problem in doing this. If other classes get access to its
instance variables directly, it can become very difficult to modify the class without
affecting other classes.

Discussion Topic 2 — concrete and conceptual classes

At the start of this unit the ideas of 'concrete' and 'conceptual' objects were introduced.
It was suggested that a 'picture' was a 'conceptual' object, not a concrete one. However,
it could be argued that a picture is 'concrete': you may have a photograph which you
can hold in your hand, so obviously it is a 'real' thing. On the other hand, you can copy a
photograph many times, and each copy would be the 'same' picture. So in that sense
there is a 'picture' which is different from the physical embodiment of the picture. Which
point of view do you think is correct here? Is a picture concrete or conceptual? This is
not an abstract academic discussion; in some computer applications an understanding
of this issue is essential to efficient use of the
computer.

Contribution for Discussion Topic 2 — concrete and conceptual classes

Contribution for Discussion Topic 2 — concrete and conceptual classes

The purpose of this exercise is to help ensure that students are familiar with the
distinction between class and object, and between 'conceptual' and 'abstract' classes. It
is probably a good idea to steer discussion away from the philosophical issues of
platonic reality, etc., that tend to surface at this point if the students are well-read.

In some senses this issue is related to the distinction between software and hardware. If
I buy a piece of software from a supplier, I may receive a CD-ROM. But the CD-ROM
containing the software is different from the software itself. I could receive the same
software in a number of different forms, e.g., on a floppy disk. I could even download
the software from a Web site in which case there is no physical medium of delivery at
all. The software is `conceptual' while the medium it delivered on is `concrete'.

Why is this important? Consider the case of a records system for a large library. It has,
say, 100,000 different books in stock, of which there are an average of 5 copies of each
book. A book has both a conceptual and a concrete component. A particular copy of a
book is definitely concrete: it is a real, physical object. This is what a library user will
borrow and pay fines on if not returned on time. However, the `conceptual book' is the
content of the book, its author, date of publication etc. We could represent this in Java
as follows:

class ConceptualBook

String Author, Title, ShelfMark, ISBNNumber;

int numPages, yearOfPublication;

class ConcreteBook

ConceptualBook conceptualBook;

boolean onLoan;

int daysLate;

Each `ConcreteBook' object contains a reference to the `ConceptualBook' of which it is


a physical copy. In the libraries database of books there will be 100,000
ConceptualBook objects, and 500,000 ConcreteBook objects (as there are five physical
copies of each book, on average). As we have defined it, ConceptualBook has 6
instance variables, while ConcreteBook has 3. So the total number of variables that the
system must manage is

100,000 * 6 + 500,000 * 3

or 2.1 million variables. This will require a lot of memory. However, consider the case
where we don't distinguish between the concrete and conceptual books. Now we need
to define the class like this, as one class must contain all the data:

class Book

String Author, Title, ShelfMark, ISBNNumber;

int numPages, yearOfPublication;

boolean onLoan;
int daysLate;

So now we have 8 variables in each class, and 500,000 objects of this class. So the
system must now deal with 4 million variables.

So by correctly distinguishing between concrete and conceptual objects, we have


almost halved the amount of storage required by the system. Moreover, if we want to
tell whether two physical books are in fact the same title (e.g., two different copies of
Tolstoy's War and Peace) this is very easy when the concrete and conceptual classes
are separated. We simply look at the references to the conceptual book in each
concrete object, and see if they refer to the same instance of ConceptualBook. If they
do, we are looking at two copies of the same book. If we don't distinguish, the only way
we can tell whether two books are copies of the same title is by comparing all the
attributes.

Reflection on Learning Experience

In your Learning Journal write up your experience of your learning on this unit. Say
what you thought was good or bad, what you had difficulty understanding, and how you
resolved your problems.

Additional Content

Destructor methods

Objects can be created and destroyed by programs. Part of a class definition can be a
method, called a destructor, that is executed when the object is to be destroyed. In Java
such a method must have the identifier finalise, and an example might be:

protected void finalise()

System.out.println("now destroying object");

This particular destructor method is not very useful, however, it illustrates that it is
possible to add a destructor method to classes, so that actions can be performed by an
object being destroyed.

Abandoned objects
If an object is created, but no variable refers to it, then this object is actually wasting
computer memory, since it can never be used. It is not possible to 'search' through
computer memory for objects of a given class — who knows, your program might find
part of some word processor document, or part of a database, stored in memory by
some application, and think it was an object

Therefore, once an object is no longer referred to by any variable of a program, that


memory can be though of as available for some other program to use.

Of course, it is very rare that a situation might occur where objects would be created
and never referred to. However, what is much more common is that objects get created,
refereed to by a variable, used for some purpose, and then the variable is used to refer
to some other object. This is the abandoning of objects.

When a system needs memory, it can perform a task called garbage-collection to find
all abandoned objects, destroy them (i.e. call their destructor methods) and free up their
memory for other uses.

Subclasses

A key feature of object-oriented programming is that classes can be extended in


subclasses. If we say that class X is a subclass of class Y, this means that X inherits all
the methods and variables of Y, and perhaps more. This is a very important
organisational feature, which will be covered in more detail in the next unit. One class is
defined as a subclass of another by using the extends keyword. This will be covered in
much more detail later in the course.

Additional Activity 1 — Revisit development of BallWorld classes

Go back to unit 2, and work through the BallWorld activities again.

Discussion of Additional Activity 1

Revisit development of BallWorld classes


You should now find you understand the majority of the implementation of each
BallWorld class.

There are some additional exercises in this section. They provide an opportunity to
recap on some general object concepts, and explore some notation ideas for graphical
representing object concepts.

Additional Exercise 2 — Bad classes

In implementing a piece of software, all of the following are potentially ‘bad’ classes.

 Central processing unit


 Joe Bloggs, a customer
 Linked list
 Data file
 Keyboard
 Miscellaneous

By 'bad' it is meant that they may not be useful things to represent as classes in a
program.

Why? (The reason is different for each)

Discussion of Additional Exercise 2

Bad classes

Suggested reasons for why each listed class is a poor idea:

Central processing unit: this is a bad class because it's got nothing to do with what the
program does. It's about what the computer does. In programming, we don't normally
have to be concerned what's going on inside the central processing unit. Exception: a
piece of software for designing computers.

Joe Bloggs, a customer: a particular customer is an object, not a class. The class
Customer might be useful.

Linked list: if you've never heard of a linked list, then this is a good reason for not
allowing it as a class. Classes are useful for explaining how programs work to a non-
specialist. The use of classes that no-one understands does not help with this aspect of
design. In fact, a linked list is a mechanism for a computer to group together lists of
data. Again, at the design stage you should not be worrying about how your program's
data is structured internally.
Data file: essentially this is bad for the same reason as `linked list'. In addition it is
vague. What is `data'? Exception: a program for checking for computer viruses. Files
are very important here.

Keyboard: a keyboard is a device for entering data. A designer should be interested in


what the data represents, not how it will be entered.

Miscellaneous: this is a bad class because it is unnecessary. If you have used object
oriented design correctly, then everything should fit neatly into one class or another.
You should have no bits left over that have to go into a `miscellaneous' class

Additional Exercise 3 – UML object-oriented notation

Object-oriented design is often supported by diagrams showing the relationships


between classes. The standard notation for this is called UML (unified modelling
language). Find out the basic symbols for class modelling used by UML. Don't spend
too long on this, and don't go into it in too much detail. For this course you will need to
know about 1% of the full UML notation! Hint: do a Web search for `UML'.

Discussion of Additional Exercise 3

UML object-oriented notation

The reference site for UML notation is held by Rational Software Inc. Try
http://www.rational.com/uml. However, their documents are extremely long and
complex, as you would expect for the specification of a major modelling language. More
useful sites on UML can be found by doing a search for `UML overview' or `UML
tutorial'.

Before proceeding to the next unit you should work through this set of review questions.
When you have completed the questions you will be able to obtain the answers for
future reference.

Your performance with these questions will not affect your grade for the module, but
may be monitored so that your tutor can be alerted if you are having difficulty.

Please contact your tutor if you feel you have not done as well as you expected.
Now complete the end of unit review questions online.

Vous aimerez peut-être aussi