INFORMATION & COMPUTER SCIENCE DEPARTMENT, KFUPM
ICS102, SECTIONS 52, 54 & 55
(001 Semester)
INTRODUCTION TO COMPUTING
LAB #09 Classes and Type definitions
Instructor: Bashir M. Ghandi
To gain experience with:
Most of the times we would like our classes to
behave as types. That is, we would like
to create more than one object (instance) of a given class, with each object
having the fields and/or methods defined in the class.
For example, just like we would like to define more
than one integer variable: int n1, n2;
We would like to create more than one Point objects
(say) from the Point class:
Point p1, p2;
We saw in the last Lab that to be able to do this,
we must declare fields and methods as non-static.
We also saw that we need to have constructors,
which are used to create and initialize objects, since unlike primitive
variables which are initialized directly as in:
n1=10; n2=15;
Objects are initialized using a constructor and the
new keyword as in:
p1 = new Point(10, 7);
p2 = new Point(20, 8);
Example1: The following defines a
Point class, which can then be used to create a Point object.
class Point { private double x; private double y; public Point(double x1, double y1) { x=x1; y=y1; } public double distanceToOrigin() { return Math.sqrt((x * x) + (y * y)); } public double distanceToPoint(Point p) { return Math.sqrt(((x - p.x)*(x - p.x))+((y - p.y)*(y - p.y))); } public void moveTo(double x1, double y1) { x=x1; y=y1; } public void translate(double dx, double dy) { x += dx; y += dy; } public double getX() { return x; } public double getY() { return y; } } |
Notes:
·
When
defining a class, we should implement all the methods of the class that we can
think of, including those that are not needed in our current application. This allows the class to be reused in other
applications. Reusability is one
of the most important advantages of Java.
·
The
fields of a class are usually declared as private so that they can only
be modified by methods of the particular object. This ensures integrity and security of the object. Imagine
another customer being able to withdraw from your account!
·
Methods
can be declared before or after the fields in a class.
·
Methods
that modify the fields of an object are called mutator methods. Example
are: moveTo and translate.
·
Methods
that do not modify the fields but only access them to compute and return some
result are called accessor methods.
Example: getX, getY, distanceToPoint
& distanceToOrigin
Before we see how the above class may be used in an
application, let us introduce two important things that are very useful when
designing a class; overloading and the this keyword.
Overloading:
It is possible to have more than one constructor in
a class (of course with the same name as the class) provided each has different
signature (i.e. different number or types of parameters). This is called overloading. For example, another constructor for the Point
class might be:
public Point() {
x=0;
y=0;
}
A constructor that does not have any parameter such
as the above is called the default constructor. If a default constructor is not defined, the
compiler automatically creates one that initializes the fields to their default
values as show by the table below.
Type |
Default Value |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Note that local variables (those declared in a method) are not
initialized automatically.
Overloading is also allowed on methods. We can have methods with the same name
provided the signature is different.
For example all the following max methods could be defined in the same
class.
public static double max(double a, double b) {
if (a >= b)
return a;
else
return b;
}
public static String max(String a, String b) {
if (a.compareTo(b) > 0)
return a;
else
return b;
}
public static Point max(Point a, Point b) {
if (a.distanceToOrigin() > b.distanceToOrigin())
return a;
else
return b;
}
The this keyword
In the definition of the constructor, we have to use
x1 and y1 as parameters.
public Point(double x1, double y1) {
x=x1;
y=y1;
}
This is because, if we were to use x and y
then we cannot access the fields of the object which are also x and y. To solve this problem, java provides the this
keyword which is used as a reference to the current object. Thus, this.x means the object
variable x. We can therefore
modify the above method as:
public Point(double x, double y) {
this.x=x;
this.y=y;
}
The this keyword can also be used to refer to
methods of this object. It is in fact a
common practice to use this to create another constructor using another. For example, the default constructor of the Point
class can be implemented by calling the other constructor as follows: public
Point() {
this(0.0, 0.0);
}
With these modifications, the Point class is
updated as follows:
class Point { private double x; private double y; public Point(double x, double y) { this.x=x; this.y=y; } public Point() { this(0.0, 0.0); } public double distanceToOrigin() { return Math.sqrt((x * x) + (y * y)); } public double distanceToPoint(Point p) { return Math.sqrt(((x - p.x) * (x - p.x)) + ((y - p.y) *
(y - p.y))); } public void moveTo(double x, double y) { this.x=x; this.y=y; } public void translate(double dx, double dy) { x += dx; y += dy; } public double getX() { return x; } public double getY()
{ return y; } public String toString() { return
"("+x+", "+y+")"; } public
boolean equals(Point p) { return
(this.x == p.x && this.y == p.y); } } |
toString and equals method.
Every object has a default toString
and equals methods. The toString
is used to convert an object to string.
The toString method is automatically invoked when the
object is used where a string is expected, example in println
method. You can specify how an object
is printed by re-defining its toString method.
Similarly, the equals method is used
to compare the current object with another object of the same class. It is important to note that objects are not
compared using the == operator, as this only compares the references of
the two objects and not the actual objects.
Again one can override the default equals method by
defining one in the class.
Example 2: The following example shows how the Point
class may be used:
import TextIO; class TestPoint { static TextIO stdin = new TextIO(System.in); public static void main(String[] args) throws
java.io.IOException{ double x,y; System.out.print("Enter
first point: "); x=stdin.readDouble(); y=stdin.readDouble(); Point p1 = new
Point(x,y); System.out.print("Enter
second point: "); x=stdin.readDouble(); y=stdin.readDouble(); Point p2 = new
Point(x,y); System.out.println("Distance
of "+p1+ " to origin = "+p1.distanceToOrigin()); System.out.println("Distance
of "+p2+ " to origin = "+p2.distanceToOrigin()); System.out.println("Distance
between "+p1+" and "+p2+ " =
"+p1.distanceToPoint(p2)); } } |
Note that in the println() statements
above, each time we have . . +p1+ . .
the toString() method is called to convert p1 to
String.
Example 3: The following implements an Account class.
class Account { private
static int numberOfAccounts = 0; //this belongs to the class private
double balance; private
int accountNumber; private
String holdersName; public
Account(String holdersName, double amount) { if
(amount >= 0) balance = amount; numberOfAccounts++; accountNumber=numberOfAccounts; this.holdersName
= holdersName; } public
Account(String holdersName) { //in
case no initial amount is given this(holdersName,
0); } public
Account(double amount, String holdersName) { //if amount is given first this(holdersName,
amount); } public
void deposit(double amount) { if
(amount > 0) balance+=amount; } public
void withdraw(double amount) { if
(amount <= balance) balance-=amount; } public
void transferTo(Account account, double amount) { if
(amount < balance && amount > 0) { withdraw(amount); account.deposit(amount); } } public
void showBalance() { System.out.println("\nAcc#:
"+accountNumber); System.out.println("Holder's
Name: "+holdersName); System.out.println("Balance:
"+balance); } public
String toString() { return
"\nAcc#: "+accountNumber+"\nHolder's Name:
"+holdersName+"\nBalance: "+balance; } } |
Note: It does not make sense for the number of
accounts to belong to an object. There
should be only one copy of this, so it is declared as static (i.e. it
belongs to the class).
Example 4: The following shows how the Account
class may be used.
import TextIO; class TestAccount { static TextIO stdin = new TextIO(System.in); public static void main(String[] args) throws
java.io.IOException{ double amount; String name; System.out.print("Enter name of first Customer:
"); name=stdin.readString(); System.out.print("Enter initial amount: "); amount=stdin.readDouble(); Account acc1 = new Account(name,amount); System.out.print("Enter name of second customer:
"); name=stdin.readString(); Account acc2 = new Account(name); acc1.showBalance(); acc2.showBalance(); System.out.print("\nEnter amount to transfer :
"); amount=stdin.readDouble(); acc1.transferTo(acc2,amount); acc1.showBalance(); acc2.showBalance(); System.out.println(acc1); } } |
1. Implement a class Employee with the following
fields, constructors and methods:
Fields:
name;
salary;
Constructors:
public Employee(String name,
double salary)
public Employee(double salary,
String name)
public Employee(String name) //this should initialize the salary to 0.0
Methods:
public String getName()
public double getSalary()
public void raiseSalary(double
percentageIncrease)
public void printEmployee() //prints the employee’s name and Salary
public String toString()
Write an
application TestEmployee that reads the names and salaries of two
employees and make use of the Employee class to create two Employee
objects and print them. Next, read a
percentage increase in salary for each employee and call the raiseSalary()
method to increment each and print the
objects again.
2.
Implement a Student
class with the following fields, constructors and methods:
Fields:
name;
totalScore;
numberOfQuizzes;
Constructors:
public Student(String name,
double score)
public Student(double score,
String name)
public Student(String name) {
Methods:
public String getName()
public double getAverage() //this
should return zero if no quiz has been taken.
public double getTotalScore()
public void addQuiz(double
score)
public void printStudent() //this should print the student’s name
and average score
public String toString()
Write an
application TestStudent that reads a student name and use the Student
class to create a Student object. Then
read the scores of the student in three quizzes and add each to the totalScore
of the student using addQuiz() method and print the student
object.
3. Home Work
Implement
a Fraction class with the following fields, constructors and
methods.
Fields:
numerator
denominator
Constructors:
public
Fraction(int numerator, int denominator) //this should make use of gcd to
reduce the fraction to simplest form
public
Fraction(int numerator) //initializes
denominator to 1
public
Fraction() //initialize numerator to
zero and denominator to 1
Methods:
private
static gcd(int n, int m) //returns the
greatest common divisor of n and m.
public
void setValue(int numerator, int denominator) //this should make use of gcd to
reduce the fraction to simplest form
public
void setValue(Fraction f)
public
int getNumerator()
public
int getDenominator()
public
double toDouble()
public
String toString() //should return the
fraction in the form: “numerator / denominator”
public
boolean equals(Fraction f)
public
Fraction reduce(Fraction f) //reduces a fraction to its simplest form –divide
both values by their gcd.
public
Fraction add(Fraction f) //Hint: a/b + c/d
= (a*d + c*b)/(b*d)
public
Fraction multiply(Fraction f)
public
Fraction divide(Fraction f)
Note: The
methods, add, multiply and divide should return the Fraction in its simplest
form.
Now to test your Fraction class, write a menu-driven application, TestFraction, that reads two fractions and perform the selected operation.
|