Classes
Objective #1: Use and implement classes appropriately.
- An accessor method is a method in a class
that only accesses private properties and that does not change the values
of any properties. Often the prefix get is
used when naming accessors. Sometimes it is convenient to provide one accessor
method for each private property in a class.
- A modifier method is a method in a class
that changes the value of a property. Often, but not always, one modifier
method is provided for each property. Often the prefix set is
used in the name of a modifier. A modifier method is also known as a mutator
method.
- An actor class is a class that does work
for a client programmer. An example of an actor class is the Random class.
It would not be appropriate to build psuedorandom number generation into
every class that needs to generate its own random numbers. Usually the name
of an actor class ends with -or or -er. The Random class
that is built into Java is obviously an exception to this naming rule but
it sure is easier to work with than the
name RandomNumberGenerator.
- A utility class is a class that is not
meant to have objects instantiated. Rather, it is a collection of related
static methods and constants such as the Math class.
- A class invariant is an expression that is always true about an object variable of the class at any point while a client program executes.
- The interface of a class is simply
the list of public constructors and methods that can be used to create and
manipulate objects from the class in a client program. Think of the Java
API (Application Programmer's Interface) as being a set of class interfaces.
- The state of an object is the collection of its properties. The behavior of an object is the set of methods.
- In Java, every parameter is passed by value. This means that a copy of the value is passed to the method and not the variable or the memory address of the variable itself. When an int value is passed to a method, the value is passed. When a primitive variable such as an int variable is passed, a copy of the value that is stored in the int variable is passed. The memory address of where the int variable is stored in the memory of the computer is not passed. If the called method changes the value stored in the passed parameter, it will have no effect on the original passed parameter in the calling method. When an object variable is passed to a method, a copy of the object variable's object reference (i.e. a copy of the memory address of where the object variable is stored) is passed to the method. If the called method tries to change the object reference it will not have any affect on the original object variable in the calling method. There are no pointer variables in Java like there are in C and C++. The developers of Java wanted to avoid pointer variables which have a reputation for allowing poor C and C++ programmers to write buggy programs. You cannot pass by reference using the & like you can in C and C++ or with ByRef in Visual Basic.
- Unfortunately, it is more difficult to swap two variables
using a method in Java than it is in C++.
The following Java call statement and swap method would compile fine but it would not cause the values in calling method local variables a and b to be exchanged
call statement: swap(a, b);
public static void swap(int num1, int num2)
{
int temp = 0;
temp = num1;
num1 = num2;
num2 = temp;
}
since the changes to the formal parameters num1 and num2 in
the called method would not apply to the corresponding actual parameters a and b in
the calling method.
However, assume that there is a class named Pair that has two int properties. Then a Pair object could be passed to the following version of swap
call statement: swap(myPair);
public static void swap(Pair thePair)
{
int temp = thePair.getNum1();
thePair.setNum1(thePair.getNum2());
thePair.setNum2(temp);
}
since the properties of an object may be changed in a method even if the object itself cannot be overwritten.
You can also use an array or ArrayList to swap two values in Java. We will be learning to use these data structures later but here is a method that uses an array as a parameter to a Java swap method
public static void swap(int[] theArray)
{
int temp = theArray[0];
theArray[0] = theArray[1];
theArray[1] = temp;
}
Objective #2: Explain cohesion, coupling, & has-a relationships.
- The cohesion of a class is the amount
of cohesiveness in the class. A class is cohesive if its public methods and
constants are all related to the main purpose of the class. For example,
the Integer class would not be cohesive
if the constant PI were defined in it. A Fish class
would not be cohesive if it needlessly included method named sqrt.
- A class has a "has-a" relationship with
another class if an object of that other class is a property of the class.
For example,
if a Purse object has a Coin object
as one of its properties then you can say that the Purse class
has a "has-a" relationship with the
Coin class or just "Purse has-a Coin".
However, you would not say that "Coin has-a Purse." The has-a relationship
is a one-way,
non-commutative
relationship. If a has-a relationship exists between two classes, it is said
that they are related by composition.
- A class is coupled with another class if it has a has-a relationship with
that class. A class has low coupling if
it does not have any such dependencies on other classes. If a Purse class
includes a Coin object as a property then
the Purse class would be coupled with
the Coin class.
It is best to develop a class that is not dependent on any other class
and that has no coupling. But this is often impossible to achieve since
real
world applications have situations that must be modeled with objects inside
of other objects.
Objective #3: Interpret preconditions and postconditions.
- A precondition is something that a client programmer guarantees to a method. Usually a precondition is a statement about the parameters of the method.
- For example, in the following method
public double divide(double num1, double num2)
{
return num1 / num2;
}
an appropriate precondition would be that num2 does not equal zero.
- Often the preconditions are typed with the method itself, especially on the AP exam.
/**
Divides two numbers.
(postcondition: Returns the quotient of num1 & num2.)
@param num1 the numerator
@param num2 the denominator
(precondition: none)
*/
public double divide(double num1, double num2)
// precondition: num2 != 0
{
return num1 / num2;
}
- It is the responsibility of the client programmer to be sure that he/she does not pass parameters that violate a method's precondition.
- A postcondition is something that the method guarantees to the client programmer. Essentially, the postcondition is the description of what the method does.
- For example, in the following method
/**
Divides two numbers.
precondition: none
postcondition: Returns the quotient of num1 & num2. If
num2 is zero, zero is returned.)
@param num1 the numerator
@param num2 the denominator
@return the quotient of numerator divided by denominator
*/
public double divide(double num1, double num2)
// precondition: none
// postcondition: the quotient of num1 divided by num2 is returned. If num2 is zero, then zero is returned.
{
if (num2 != 0)
{
return num1 / num2;
}
return 0;
}
the postcondition is clearly stated within the method.
- In the free response section of the AP exam, the exam writer will provide the postcondition within the methods that have to be written. Be sure to read the postcondition carefully and make sure that you satisfy every part of it. Postconditions can be very complicated.
- If a precondition is violated when a method executes, a good class developer will throw an exception from the method. An exception is an object that indicates that an error occurred. A client program can be designed to catch exceptions in order to run more effectively.
Objective #4: Explain the difference between instance methods and static methods.
- An instance method is a method that applies to an object of a class. In a client program, you must first instantiate an object and then call one of its methods by typing the name of the method after the dot operator which is after the object variable.
- For example, the code segment
Fish nemo = new Fish();
nemo.move();
illustrates the use of the instance method move.
- A static method (also known as a class
method) is one that doesn't apply to a specific object variable
but rather is called by
typing
the name
of the class, followed by the dot operator and the name of the static method. A
static method has no implicit parameter. If getPondTemperature is a static
method in the Fish class, you would never see the code nemo.getPondTemperature() in a client program. Instead, you would use Fish.getPondTemperature(). The
object variable nemo cannot be the implicit parameter of the static method
getPondTemperature.
- For example, the code segment
System.out.println(Math.max(3, 5));
illustrates the use of the static method max which is found in the Math class.
- To write a static method within a class, the keyword static must
be used in the method header as in:
public static void maxWord(String string1, String string2)
{
if (string1 > string2)
{
return string1;
}
return string2;
}
- You could include any number of static methods in a client class along with the static method main. For example,
public static void main(String[] args)
{
intro();
body();
closing();
}
public static void intro()
{
System.out.println("Here is a story");
}
public static void body()
{
System.out.println("of a lovely lady ");
}
public static void closing()
{
System.out.println("The End");
}
Objective #5: Explain static fields.
- Static fields (also known as class
fields) are not covered
on the AP exam.
- Static fields are like module-level variables
in Visual Basic.
- It is not good style to use static fields but occasionally they are practical to use.
- Static fields should be private just
like instance fields (i.e. properties).
- Constants such as PI in the Math class are static however they are defined as public on purpose so they can be used directly by client programmers.
- As soon as the first object variable of a class is instantiated, one copy of a static field is created. All object variables share the same static field.
- Use the keyword static when declaring a static field in a class as in
private static int gameScore;
- There are three ways to initialize a static field:
- if no value is assigned, the compiler will assign the value 0, false,
or null. This is true for any instance
field (i.e. property) in a class not just static fields.
- an explicit initialization statement such as
private static int gameScore = 0;
- an initialization block such as
public class Game
{
. . .
private static int gameScore;
static
{
gameScore = 0;
}
}
Remember, as explained above, that static fields are not covered on the AP exam,
so you do not need to know the syntax above for the exam.
Objective #6: Explain scope with regard to local variables and instance fields.
- A local variable can only be used within
the method or constructor where it is declared.
- The scope of a variable is the area of
a program in which the variable can be used without causing an error. The
scope of an instance field (i.e. a property) is the class that its contained
in. The property can be used in any method that is found in the class. A
local variable that is declared in a method can only be used in
that method. An actual parameter that is passed to a method can only be used
within that method. A variable that is declared in a loop as in
for (int i = 0; i < 10; i++)
can only be used in that particular loop.
You will receive a compiler error if you have two variables with the same
name that have overlapping score as in this example:
public static void doNothing()
{
int i = 50;
for (int i = 0; i < 10; i++)
{
System.out.println(i);
}
}
- A local variable must be initialized to a value when it
is declared within a method or a compile error will result. In other words,
the statement
int num;
is illegal if used as a local variable in a method. You should initialize
the variable to a value such as zero.
int num = 0;
- A property (i.e. instance field)
is usually initialized in the constructors of the
class however the compiler will automatically initialize int and double properties
to the value zero even if you do not initialize them in a constructor.
- Usually a property (i.e. instance field) is declared as
private so it cannot be directly used in a client program.
- Shadowing results when a local variable
is given the same name as an property in the class. It is bad style to shadow
a property but the code would compile
fine.
public class Fish
{
public Fish()
{
int weight = 10;
}
. . .
private int weight;
}
In the Fish class above, the local variable
weight in the constructor does contain the value 10 but unfortunately the real
instance
field weight is not being set
to 10. It will store zero by default. Shadowing in this way causes a logic error
rather than a compile error.
Objective #7: Implement a toString method with every class that you design.
- Most classes that are built-in to Java or designed by professional programmers include a method named toString. The purpose of the toString method is to allow a client programmer to display the state
of an object. Remember that the state of an object is its set of properties and their values. So if a Fish object had myAge and myWeight properties then the statement
System.out.println(nemo.toString());
would display something like
myAge=3 myWeight = 15
- It is up to the programmer to decide how to format the String that is returned by the toString method. But the String value that is returned by the toString method should be complete and easy-to-read
and interpret by client programmers.
- Here is an example of a toString method implementation that might be found in a Fish class where a Fish object has myAge and myWeight properties
public String toString()
{
return "myAge = " + myAge + " myWeight = " + myWeight;
}
Notice the use of concatenation to "glue" the properties together into one String.
- It is a common mistake for programmers to include the actual System.out.println inside of the toString method and to make the toString method void. DO NOT MAKE THAT MISTAKE. It is conventional and
very important to be consistent with other professional programmers and to use the exact method header
public String toString()
when you implement a toString method in any class that you write.
- In a client class, the System.out.println method can be used to invoke the toString method as in
System.out.println(widget.toString());
or
System.out.println(widget);
The latter is preferable since Java automatically invokes an object's toString method when the object variable is a parameter of the println method.