Classes and Objects
Example: We are going to create a student class that holds information about the student and performs actions about the student.
public class Student
{
//Our Fields which are the information/characteristics about our objects
private String name;
private int test1;
private int test2;
private int test3;
//Constructors have the same name as the class (case-sensitive)
public Student() //no-args consructor or default constructor
{
name = "";
test1 = 0;
test2 = 0;
test3 = 0;
}
public Student(String n, int t1, int t2, int t3) //initialize constructor
{
name = n;
test1 = t1;
test2 = t2;
test3 = t3;
}
public Student(Student other)
{
name = other.name;
test1 = other.test1;
test2 = other.test2;
test3 = other.test3;
}
//Accessors
public String getName()
{
return name;
}
public int getTest1()
{
return test1;
}
public int getTest2()
{
return test2;
}
public int getTest3()
{
return test3;
}
//Modifiers
public void setName(String nm)
{
name = nm;
}
public void setTest1(int t1)
{
test1 = t1;
}
public void setTest2(int t2)
{
test2 = t2;
}
public void setTest3(int t3)
{
test3 = t3;
}
//other methods
public int getAverage()
{
return (test1 + test2 + test3)/3;
}
public String toString()
{
return "Name: " + name + "\nTest 1: " + test1 + "\nTest2: " + test2 +
"\nTest3: " + test3;
}
public boolean equals(Object other)
{
Student temp = new Student();
temp = (Student)other;
return (name.equals(temp.name) && test1 ==temp.test1 && test2
==temp.test2 && test3==temp.test3);
}
}
Fields (or Instance Variables)
Fields consist of whatever data this class needs to maintain. We declare these variables just like regular variables, with one exception - we put the keyword private in front of them. For example, in the student class, we will maintain a student's name and three test scores, so we declare the following as fields:
private String name;
private int test1, test2, test3;
So what does the keyword private do? By making fields private, we protect their values from outside manipulation. It also means that any attempt to use those variables outside of this file will meet with an undeclared identifier error. In other words, these variables are unknown outside this code (the opposite of private is public, but we will not use that keyword for fields). This is called encapsulation.
Constructors
A constructor is a method whose purpose is to instantiate or construct a new object. It is essentially a means to declare an object in a way similar to the way we declare variables, but involves more detail. In our example, we will construct a Student. This requires giving the student a name as well as values for the three test scores.
There are three types of constructors:
Default - sets fields to default values
Initializing - sets fields to user-defined values
Copy - sets fields to values copied from another object of the same type
Default values: 0 for numbers, false for booleans, and null for objects. Remember that if you try to use a method on a null object, you will get a null pointer exception.
Accessors - allow the client code access to the fields
Modifiers - allow the client code to safely make changes to the values of the fields
Other - perform various miscellaneous actions on the object (either public or private) including such tasks as output of the object
Client Code
Now that we have seen the code for the Student class, we need to learn how to use or implement the methods in a client program. A client is a program that makes use of a class. To state it another way, the program is a client of the class.
When writing client code, we must first declare an object of the type defined in the class. That means we will first make use of one of the class's constructors. Since there are two constructors, there are two ways to construct a student object. See the examples below.
Student s1 = new Student();
Student s2 = new Student("Bob", 82, 89, 64);
Using the new keyword automatically calls a constructor (One of the constructors must match exactly those parameters). The first statement above utilizes the default constructor. Since no initial values were given to this object, it received the default values (those specified in the default constructor). For our design, that means the object s1has its name initialized as an empty string and all 3 of its test scores are set to zero.
In the second statement, the object s2 is given initial values for the name and the test scores (the scores are assigned in the order they are given). This is an example of the use of an initializing constructor.
In general, the form of a constructor is
ClassName identifier = new ClassName(list of values - if any);
Accessor Methods
Once an object is instantiated, we can make use of its built-in methods. Some of the methods in our class are accessor methods, which are used to access the private fields. Typically, the names of accessor methods begin with get, since they are used to get data from the object. One such method in our class is getName(). The method getName() returns the name for the given Student object. Its method header is shown below.
public String getName()
What is this method header saying? First it tells us that this method is public, meaning that it can be invoked in any client of the Student class (a private method could only be used within the context of the class). Second, the use of the keyword String means that the method will return a String value (if a method only performs a task and does not have a return value, we make it a void method). Lastly, getName() is the name of the method and must adhere to the same naming rules for all identifiers. Since the parentheses are empty, this method has no parameters or input values. In general, method headers take this form:
public returnType methodName(parameters)
The returned value of a method has to go somewhere. Since this method is returning a String, the value has to go to a String variable or to an output statement. Here are two ways to invoke this method for the Student object s2:
println(s2.getName());
String studentName = s2.getName());
Modifier Methods
A method that safely changes the value of one of the private fields is called a modifier. The Student class method setName() is an example. The purpose of this method is to allow the user to change the internal name of a Student object. See the header of setName() below:
public void setName(String nm)
This method header tells us that it is public and void (has no return value). It is called setName and has one parameter, a String. This means we must supply the method call with a String that is intended to become the new name of the Student object. Note that the identifier nm is a temporary placeholder for this value and the value in nm gets transferred internally to the field name in the Student class.
Other Methods
In the Student class, there are other methods that are neither accessors or modifiers. These are getAverage(), equals() and toString(). These are examples of methods that perform tasks on the fields. Let's look at each one individually.
While getAverage() appears to be an accessor due to its name, it doesn't actually access data - it simply supplies more information about the data. Specifically, it computes and returns the average of the three test scores as a decimal.
The method toString() gives the class a way to output a visual representation of the object. It does so by returning a String value with all of the data from the object, including the average of the tests (using getAverage()). That String is displayed using a println() statement. For example, if we have a Student object named s, we can do the following:
println(s);
When an object is placed in a println()statement, the toString() method is automatically invoked and the output described in that method is displayed.
Note: The toString() method actually comes from the “Cosmic Superclass” Object. So all of our classes have a toString method that is not very useful, but we change it to make it useful to us.
The equals() method is a common method that we will use to determine if two objects of our class are equal. For two students to be equal, they have to have the same name and the same test scores for test1, test2, and test3.
Unit 4 Problem Set:
Project 1: Rectangle Class
Class: Rectangle
Fields: length, width (can be integers)
Constructors: no-args, initialize, copy
methods: accessors, modifiers, getArea, getPerimeter, getLengthOfDiagonal
isSquare // checks to see if the rectangle is a square
quadratize // converts the rectangle into a square with approximately the same area- the closest possible for a square with an integer side
Create a tester class and test thoroughly!
Project 2:
Class: Fraction
Fields: numerator, denominator
Constructors, no-args (0/1), initialize (2 ints), initialize (1 int), copy
methods:
accessors and modifiers for fields
void reduce()
Fraction add(Fraction other)
Fraction subtract(Fraction other)
Fraction multiply(Fraction other)
Fraction divide(Fraction other)
double toDecimal()
String toString()
boolean equals(Object other)
Project 3:
Class: Student
Fields: String name, int test1, int test2, int test3
Methods: Accessors, modifiers, double getAverage(), void replaceLowestGradeWithAverage()
String toString() which should return:
i.e. Craig Sapp has a test average of 53.
Class: APStatsStudent
Description: An APStatsStudent “is-a” Student, however, we add a new field which is the double HomeworkAverage.
Create a constructor using the super keyword that accepts a String, three ints, and a double.
Override getAverage() from the Student class so that the student’s average is
.6(testAverage) + .4(hwAverage)
getGrade() returns A, B, C, or F
override toString() to return:
i.e. Craig Sapp has a B in AP Stats
Class: APStatsStudent
Field: APStatsStudent[] students
Methods: accessor, modifier, double getClassAverage()