Wu chapter 4: defining your own classes

advertisement
Wu chapter 4: defining your own classes
Programmer-defined class: any non-standard class is a programmer-defined class – including every
class you have written thus far
Classes consist of a set of methods and a set of data that can be manipulated by these methods; when
we define a class, we think about the thing we’re going to model, and come up with a list of
operations, or tasks, that we want the thing to do.
For example, consider a thermometer. This is an instrument that measures temperature, and displays
its reading (as a line of mercury or a set of LED digits, for example). The set of operations on a
thermometer is rather simple – basically, we just need to display the temperature.
Now consider an enhanced thermometer. Instead of just a single display function, it has three – it can
display the temperature in degrees Fahrenheit, degrees Celsius, or degrees Kelvin. We could model
such a thermometer in Java using a class similar to the following:
import java.util.*; // for Random
public class BetterTherm {
private int kelvinTemp;
private
private
private
private
final
final
final
final
static
static
static
static
// temperature in Kelvin
int CFACTOR = 273; //
int RANGE = 101;
//
int FCONVI = 32;
//
double FCONVD = 1.8;//
conversion constant for Celsius
# of values in range
conversion constant for Fahrenheit
second constant for F conversion
// Constructor: a method for initializing a data member
public BetterTherm () {
Random temp = new Random();
kelvinTemp = Math.abs(temp.nextInt());
kelvinTemp = kelvinTemp % RANGE + CFACTOR;
// initializes the temperature to somewhere between 273K and 373K // the freezing point and boiling point of water, respectively
}
// return Kelvin temperature
public int getKelvin () {
return kelvinTemp;
}
// Convert to Celcius & return
public int getCelcius () {
return kelvinTemp - CFACTOR;
}
// Convert to Fahrenheit & return
public int getFahrenheit () {
int fTemp; // Fahrenheit temperature to be returned
fTemp = (int)(FCONVD * getCelcius()) + FCONVI;
return fTemp;
}
}
Computer Science I
Sheller
Wu ch4 - laptop
Fall 2005
Page 1
This class differs from those we have created thus far in several ways:
 There are multiple methods
 There is no main method
 There are several constants and one variable that are declared inside the class, but outside any
method
Before we delve too deeply into the code for this class, let’s examine how it might be used in a
program. The class defined below declares three BetterTherm objects, then displays the temperature
each one is reading using the three different scales:
public class TestTherm {
public static void main (String [] args) {
BetterTherm bt1, bt2, bt3;
bt1 = new BetterTherm();
bt2 = new BetterTherm();
bt3 = new BetterTherm();
System.out.println ("The three thermometers are reading as follows:");
System.out.println ("\tK\tC\tF");
System.out.println ("1)\t" + bt1.getKelvin() + "\t" + bt1.getCelsius() +
"\t" + bt1.getFahrenheit());
System.out.println ("2)\t" + bt2.getKelvin() + "\t" + bt2.getCelsius()+
"\t" + bt2.getFahrenheit());
System.out.println ("3)\t" + bt3.getKelvin() + "\t" + bt3.getCelsius() +
"\t" + bt3.getFahrenheit());
}
}
The output looks like this:
The three thermometers are reading as follows:
K
C
F
1)
350
77
170
2)
371
98
208
3)
322
49
120
Both the BetterTherm class and the TestTherm class follow the syntactic pattern that should be
familiar by now:
public class ClassName {
// class members defined here
}
The BetterTherm class has several data members. A member variable or constant is a variable or
constant that belongs to the class (or object), but not to any particular method within the class.
Because both member data and member methods end up being part of the same object when a class is
instantiated, member data items are accessible from all member methods, and a member method can
Computer Science I
Sheller
Wu ch4 - laptop
Fall 2005
Page 2
call another member method. Access to data or methods by any other type of objects is restricted by
the visibility modifier. Two types of accessibility are used in BetterTherm: public and private.
 a public member of a class is visible to the world in general; methods are usually public
 a private member (usually data, but methods can also be private) is accessible only to the
methods defined within the class
The data members of BetterTherm include a single instance variable, kelvinTemp, and several class
constants.
 An instance variable is a variable belonging to an object – when a BetterTherm object is
created, it gets its own unique kelvinTemp variable. As we have already seen, the value of this
variable can be different from object to object. The positioning of the declaration – inside the
class but outside any method – makes a variable an instance variable, rather than a local
variable.
 A local variable is a variable declared inside a method. The variable fTemp in the
getFahrenheit() method is an example of a local variable.
 A class variable or class constant is one that is shared by all instances of a class; in other
words, it exists in just one place in memory, and all objects of the class type are able to access
its value. The keyword static is used to declare a class data member (or method).
 Both class variables and instance variables may be referred to by name in any member method,
while a local variable can only be referred to within the method in which it is declared.
This restriction on the ability to refer to a variable is called the scope of the variable. In
general, the scope of a local variable is limited to its method, while the scope of a class or
instance variable is class-wide.
Most of the methods defined in the BetterTherm class are value-returning methods. When an object
or class receives a message to one of its value-returning methods, it returns a value matching its
specified return type to the calling object.
The syntax for a method heading is generally:
modifier(s) returnType name (parameter(s)) where:
 Modifiers include visibility modifiers (e.g. public or private) and occasionally other modifiers,
such as static.
 The return type of a method indicates what kind of data value, if any, the method will return
when it concludes. In BetterTherm, the getKelvin, getCelsius and getFahrenheit methods all
have the return data type int. This means that a message requesting one of these methods can
be used in an expression by the calling object. An example from TestTherm:
System.out.println ("1)\t" + bt1.getKelvin() + "\t" + bt1.getCelsius() +
"\t" + bt1.getFahrenheit());

As we have already seen, this line of code prints out the three return values from the three
messages to bt1 from TestTherm. The three "get" methods of the BetterTherm class are all
value-returning, so they all contain a statement at the end indicating the value to be returned.
The general syntax for a return statement is:
return expression;
where expression evaluates to a result that is the same data type as the one indicated as the
return type in the method heading. Some examples in the BetterTherm class include:
Computer Science I
Fall 2005
Sheller
Page 3
Wu ch4 - laptop
return kelvinTemp - CFACTOR;
from getCelsius and
return fTemp;

from getFahrenheit.
It is possible that we don’t want the method to return a value. In that case, we use void as
the return type. This is the approach we have always used with main():
public static void main (String [] args) {


The name of a method is simply a valid identifier that will be used to call the method. The
identifier main is a special case, since this method executes automatically when a program
starts, and not in response to a message. In all other cases, we use the method’s name in the
message that requests its execution.
The parameter list indicates what kind(s) of data, if any, are required for the method to
accomplish its task. None of the methods defined so in the BetterTherm class requires an
argument, so their parameter lists are empty. The parameter list of TestTherm’s main method
(like all main methods) contains a single parameter:
(String [] args)
You should recognize that String is the name of a class from the Java API. The identifier for
the parameter is args; the notation [] indicates that args is a special kind of variable called an
array, which we will talk about several weeks from now. Here’s what you should know about
parameters:
 Parameters are declared just like variables or objects.
 The scope of a parameter is the same as the scope of a local variable; in other words,
local to its method. This has some added implications:
o You can use the same name for local variables and parameters as long as they
are in different methods
o You shouldn't use the name of a class-wide variable, constant, or object to refer
to a local variable, constant or object – this makes the class-wide identifier
invisible within the local scope. Consider the example code below:
import javax.swing.*;
public class JustChecking {
private int num;
int getNum () {
return num;
}
void setNum (int n) {
num = n;
}
void badSetNum () {
int num;
String n;
n = JOptionPane.showInputDialog (null, "Enter a number:");
num = Integer.parseInt(n);
}
}
Computer Science I
Sheller
Wu ch4 - laptop
Fall 2005
Page 4
The identifier num is used both for the instance variable and a local variable in the badSetNum
method. Consider the last line in the badSetNum method: which num (local or class-wide) is assigned
a value here?
We can find out by writing a program that uses this class, as in the example below:
import javax.swing.*;
public class TestJC {
public static void main (String [] args) {
JustChecking jc = new JustChecking();
String s = JOptionPane.showInputDialog (null, "Enter a test value:");
jc.setNum(Integer.parseInt(s));
JOptionPane.showMessageDialog (null, "You entered: " + jc.getNum ());
jc.badSetNum();
JOptionPane.showMessageDialog (null, "You entered: " + jc.getNum ());
}
}
// 1
// 2
// 3
// 4
A sample run of the program is shown below:
Windows 1, 2 and 4 come from lines of code in the main method of TestJC. Window 3 comes from
the badSetNum method of JustChecking. The local variable num in badSetNum is set to 333, but the
classwide instance variable num retains its original value (1001). If another name had been used for
the local variable in badSetNum, then the instruction (in badSetNum):
num = Integer.parseInt(n);
would have applied to the instance variable.
The JustChecking class gives an example of another method that has a parameter. The setNum method
takes a single int argument, which is stored in parameter n. This value is then assigned to the instance
Computer Science I
Sheller
Wu ch4 - laptop
Fall 2005
Page 5
variable num. The setNum method is an example of void, or non-value-returning method; it is also an
example of a modifier, or a method that changes its object.
Parameter matching
 Parameters specify the number, ordering, and data type(s) of the argument(s) that can be passed
to a method.
 When a parameter is one of the simple numeric types, we can pass as an argument to the
parameter any expression that is assignment-compatible with the parameter’s specified data
type. Recall that expressions can include:
o literal values, e.g. -4, 13.02
o initialized variables or constants
o messages to value-returning methods (e.g. Integer.parseInt(), Math.sqrt(a))
o arithmetic operators & parentheses
o explicit type casts
Assignment compatibility means that the value being passed is only valid if it can be assigned
to a variable of the parameter’s type. For example, while we can pass an int value or variable
as an argument to a double parameter, we cannot pass a double value or variable to an int
parameter unless we explicitly cast the argument as an int.
 Parameters, as we’ve already seen, are variables local to the method they are declared in. As
we already know, all variables have two properties: a data type and an identifier.
 Arguments can have identifiers too. If we pass a variable or constant as an argument, we are
passing a named argument.
 There is no relationship between the name of a parameter and the name of its
corresponding argument. This means:
o They can have different names (and usually do).
o They can have the same name, because they belong to different methods, and thus have
different scope.
o Consider the code below:
public class SimpleClass {
private int x;
public void setVar (int y) {
x = y;
}
int getVar () {
return x;
}
}
import java.util.*;
public class TestSimp {
public static void main (String [] args) {
SimpleClass simp = new SimpleClass();
int x;
Scanner kb = new Scanner (System.in);
System.out.print ("Enter a whole number: ");
x = kb.nextInt();
simp.setVar(x);
System.out.println ("Value of SimpleClass’s x = "
+ simp.getVar());
x += 10;
System.out.println ("Value of TestSimp’s x = " + x);
System.out.println ("Value of SimpleClass’s x = "
+ simp.getVar());
simp.setVar();
}
}
Computer Science I
Sheller
Wu ch4 - laptop
Fall 2005
Page 6
In the first call to setVar, argument x’s value is passed to the method’s parameter y; this value is then
assigned to SimpleClass’s x variable. When the x variable’s value changes in TestSimp’s main
method, the change has no effect on x or y in SimpleClass.
Class constructors
 The BetterTherm class has one more method we haven’t discussed yet. It looks like this:
public BetterTherm () {
Random temp = new Random();
kelvinTemp = Math.abs(temp.nextInt());
kelvinTemp = kelvinTemp % RANGE + CFACTOR;
// initializes the temperature to somewhere between 273K and 373K // the freezing point and boiling point of water, respectively
}


This method is called a constructor; its purpose is to initialize instance variables to reasonable
values when a new object is instantiated.
Characteristics of constructors:
o identifier is the same as the class’s (so BetterTherm’s constructor is named
BetterTherm)
o a call to a constructor occurs when the new operator is invoked – so, for example, the
following lines of code in TestTherm:
BetterTherm bt1, bt2, bt3;
bt1 = new BetterTherm();
bt2 = new BetterTherm();
bt3 = new BetterTherm();
represent 3 calls to BetterTherm’s constructor.
Accessors, constructors and mutators
 Most classes contain three kinds of methods:
o Constructors, as we’ve seen, initialize data members of new objects.
o Accessors report on the state of an object, usually by returning a data item from the
object; in all the classes we’ve used as examples, the “get” methods are accessors.
o Mutators are those methods that change the state of an object; this usually means they
assign new value(s) to member variable(s). The “set” methods of the example classes
are mutators.
 Since data members are usually declared private, the only access to the data in an object is
via the class methods. This protects data integrity by ensuring that there are no “back door”
mechanisms by which a client programmer can tamper with the data in an object.
As originally written, the BetterTherm class had no mutators; once the temperature value was set by
the constructor, the reading will always be the same. Of course, if we had a real thermometer, a
change in temperature in the environment would change the temperature reading on the gauge. We
don’t have a mechanism to simulate environmental conditions (yet), but we can at least provide some
methods to manually set the temperature. To provide maximum flexibility, we will allow the
temperature to be set using a value representing any of the three scales, then we’ll have the method
convert the temperature to Kelvin (if necessary).
The new methods would appear in the public section of the class:
Computer Science I
Sheller
Wu ch4 - laptop
Fall 2005
Page 7
public void setKtemp (int k)
{
kelvinTemp = Math.abs(k);
}
public void setCtemp (int c)
{
kelvinTemp = c + CFACTOR;
}
public void setFtemp (int f)
{
int cTemp = (int)((f - FCONVI) / FCONVD);
kelvinTemp = cTemp + CFACTOR;
}
One more code example:
import java.text.*;
import java.util.*;
import javax.swing.*;
public class BigSign {
private Date time;
private BetterTherm temp;
private String adMsg;
private String jokeMsg;
public BigSign () {
time = new Date();
temp = new BetterTherm();
adMsg = new String ("Buy this now!");
jokeMsg = new String ("Time flies like an arrow,\n" +
"fruit flies like a banana");
}
public void displaySign() {
SimpleDateFormat sdf = new SimpleDateFormat ("hh:mm");
JOptionPane.showMessageDialog(null, adMsg);
JOptionPane.showMessageDialog(null, "" + sdf.format(time) + "
temp.getFahrenheit());
JOptionPane.showMessageDialog(null, jokeMsg);
}
" +
public void setAdMsg (String newAdMsg) {
adMsg = newAdMsg;
}
public void setJokeMsg (String newJokeMsg) {
jokeMsg = newJokeMsg;
}
public void setTime (Date t) {
time = t;
}
Computer Science I
Sheller
Wu ch4 - laptop
Fall 2005
Page 8
public void setTemp (BetterTherm t) {
temp = t;
}
public static void main (String [] args) {
BigSign mySign = new BigSign();
Random randGen = new Random();
Date newTime = new Date((long)(randGen.nextInt()));
BetterTherm bt = new BetterTherm();
mySign.displaySign();
mySign.setAdMsg("Read this sign!");
mySign.setJokeMsg("Why did the pig cross the road?\n" +
"He was stapled to the chicken");
mySign.setTime(newTime);
mySign.setTemp(bt);
mySign.displaySign();
System.out.println(mySign.toString());
}
}
The BigSign class illustrates several principles:
 Objects can be declared as class instance variables, parameters, or local variables, just as
simple type variables can. BigSign contains an instance variable of type BetterTherm (as well
as a Date object and two String objects).
 Because the class models an electronic sign, its most commonly-used method would probably
be its displaySign method, which displays (using message windows), an advertisement, the
time and temperature, and a joke. There is another method that can be used for display: the
toString method, which converts the values of all of the instance variables into a single
concatenated String object. This method is a sort of utility for client programmers; it provides
access to all of a signs “contents” without making it necessary to display those contents. It
would be possible, using String member methods, to parse this String and extract relevant parts,
discarding the rest. Alternatively, we could have included “get” messages, which could have
given access to the various parts without the necessity of String parsing.
 The class contains a main method, which demonstrates the use of the other methods. We could
still create a separate client class, as we have done with the other example classes, and that
client could have its own main method. In Java, any class can have a main method, and this
can come in handy for testing a class even if its primary use will be as a server class.
Computer Science I
Sheller
Wu ch4 - laptop
Fall 2005
Page 9
Download