Table of Contents
Point
class.A point at the plane can be represented by a pair of coordinates x and y, both with real values. In Java, we can represent a point at the plane as an instance of the following class:
public class Point {
private double x;
private double y;
/* methods */
/* to complete */
}
In Java, the constructor of a class is used to initialise the values of the attributes at the moment the object is instantiated at runtime execution.
Program a constructor for the Point
class. It must receive both point coordinates as input parameters.
The toString()
method has a special meaning for objects in Java. This method is used to get a text representation of the object as a string.
Program the toString()
method so that it returns a string with the representation of the point according to the following format:
(x, y)
where x and y must be replaced by their respectives values. The prototype of the method is specified as follows:
public String toString() { /* ... */ }
Remember that the "+" operator, applied to strings of characters, allows to concatenate them. But if you try to concatenate a number with a string, don't worry, Java converts automaticaly the number to a string to make the "addition".
main
method.Now you have to create a class to test the previous code.
Program a class called TestingPoint
which has a main
method. This method must receive, as command line arguments, the x and y coordinates, then create a new Point
object with those coordinates and print a text representation of such object to the standard output (the console).
The program must check that the number of command line arguments received is correct.
The parseDouble()
method of the
Double class
(click to follow the link to the API Javadoc) transforms a string of characters to a double
primitive type.
It is common that object's attributes are declared as private (private
)
to avoid uncontrolled accesses from other parts of the code. To provide such access from outside code, there are
special methods. Those methods usually begin with the following strings: "get
"
(read access) and "set
" (write access).
In this paragraph, we are going to implement two auxiliary methods that will allow us to calculate distances between points.
Program a method of the Point
class that returns the distance from the point to the origin of the coordinates. The prototype of the method is as follows:
public double distanceToOrigin() {
/* complete */
}
Modify the code of your TestingPoint
class to check that its behaviour is correct.
Program a method of the Point
class that returns the distance between the point represented by
the actual object instance and another instance of Point
that is received as input parameter.
The prototype of the method is as follows:
public double distance(Point anotherPoint) {
/* completar */
}
Modify the code of your TestingPoint
class to check that its behaviour is correct.
Program a method of the Point
class that returns the quadrant in which the point is located. The prototype of the method is as follows:
It returns 0 if it is placed at the origin of coordinates or on any of the axis.
It returns 1 if it is placed at the first quadrant (both x and y positives).
It returns 2 if it is placed at the second quadrant (x negative and y positive).
It returns 3 if it is placed at the third quadrant (both x and y negatives).
It returns 4 if it is placed at the fourth quadrant (x positive and y negative).
The prototype of the method is shown below:
public int quadrant() {
/* complete */
}
Modify the code of your TestingPoint
class to check that its behaviour is correct.
This section is based on the previous methods you have implemented before.
Program a method of the Point
class that receives, as input parameter, an array of
Point
objects and returns a reference to the object of the array that represents the nearest point to the current object (this).
The prototype of the method is as follows:
public Point nearest(Point[] otherPoints) {
/* complete */
}
Modify the code of your TestingPoint
class to check that its behaviour is correct.
Triangle
class.A triangle is fully defined by three of its vertexes. These vertexes can be represented as
objects of the Point
class.
This section is based on the previous methods you have implemented before.
Program the Triangle
class with its attributes and a constrctor
that receives three points (vertexes) as input parameters.
Program a class to test it.
The solutions of this exercise are included in the following listings:
// Point class
// (c) 2008 IT
public class Point {
private double x;
private double y;
// Constructor
public Point(double x, double y) {
this.x = x;
this.y = y;
}
/**
* Returns the coordinates of the point in a string
*/
public String toString() {
// '+' operator in String objects does not mean mathematical sum, but
// concatenation of strings
return "(" + x + ", " + y + ")";
}
/**
* Returns the distance to the origin
*/
public double distanceToOrigin() {
// It can be also calculated calling to
// distance(new Point(0,0))
return Math.sqrt(x * x + y * y);
}
/* Getter methods */
public double getX() {
return x;
}
public double getY() {
return y;
}
/** Returns the distance to another point */
public double distance(Point anotherPoint) {
double x1;
double y1;
x1 = x - anotherPoint.getX();
y1 = y - anotherPoint.getY();
return Math.sqrt(x1 * x1 + y1 * y1);
}
/** Returns the quadrant */
public int quadrant() {
if (x > 0.0 && y > 0.0) {
return 1;
} else if (x < 0.0 && y > 0.0) {
return 2;
} else if (x < 0.0 && y < 0.0) {
return 3;
} else if (x > 0.0 && y < 0.0) {
return 4;
} else {
// (x==0.0 || y==0.0)
return 0;
}
}
/**
* Returns the nearest point of the array in the parameter or null if array is
* empty
*
* @param otherPoints
* @return
*/
public Point nearest(Point[] otherPoints) {
Point nearestPoint = null;
double minDistance;
double distance;
if (otherPoints != null && otherPoints.length > 0) {
// Start storing the first point in the array as the nearest one
minDistance = distance(otherPoints[0]);
nearestPoint = otherPoints[0];
for (int i = 1; i < otherPoints.length; i++) {
// If nearer point is found, this is the new nearest one
distance = distance(otherPoints[i]);
if (distance < minDistance) {
distance = minDistance;
nearestPoint = otherPoints[i];
}
}
}
return nearestPoint;
}
}
// TestingPoint
// (c) 2007 IT
public class TestingPoint {
public static void main(String args[]) {
// Check the number of arguments (the two coordinates)
if (args.length != 2) {
System.out.println("Usage:");
System.out.println(" java TestingPoint x y");
System.out.println("where x and y are the coordinates of a point.");
return;
}
// Handle exceptions
try {
double x = Double.parseDouble(args[0]);
double y = Double.parseDouble(args[1]);
Point p = new Point(x, y);
System.out.println("The point is " + p.toString());
System.out.println("Its distance to origin is " + p.distanceToOrigin());
System.out.println("Its X coordinate is " + p.getX()
+ " and its Y coordinate is " + p.getY());
System.out.println("It is located in the quadrant" + p.quadrant());
Point[] pointsArray = new Point[5];
pointsArray[0] = new Point(1, 1);
pointsArray[1] = new Point(5, 3);
pointsArray[2] = new Point(10, 10);
pointsArray[3] = new Point(-3, 2);
pointsArray[4] = new Point(-4, -5);
for (int i = 0; i < pointsArray.length; i++) {
System.out.println("Its distance to the point "
+ pointsArray[i].toString() + " is " + p.distance(pointsArray[i]));
}
System.out.println("The nearest point is " + p.nearest(pointsArray));
} catch (Exception e) {
System.out.println("Error in the arguments of the command line.");
return;
}
}
}
// Testing triangle
// (c) 2007 IT
public class TestingTriangle {
public static void main(String args[]) {
// Checking number of arguments(Two coordinates for every point)
if (args.length != 6) {
System.out.println("Usage:");
System.out.println(" java PruebaTriangulo x1 y1 x2 y2 x3 y3");
System.out.println("where (xi,yi) are the coordinates of every vertex");
return;
}
// Handle exceptions
try {
double x1 = Double.parseDouble(args[0]);
double y1 = Double.parseDouble(args[1]);
double x2 = Double.parseDouble(args[2]);
double y2 = Double.parseDouble(args[3]);
double x3 = Double.parseDouble(args[4]);
double y3 = Double.parseDouble(args[5]);
// Vertexes and the triangle are finally created
Point v1 = new Point(x1, y1);
Point v2 = new Point(x2, y2);
Point v3 = new Point(x3, y3);
Triangle t = new Triangle(v1, v2, v3);
// Displaying the info
System.out.println("The triangle has vertexes " + v1.toString() + ", "
+ v2.toString() + ", " + v3.toString());
double[] edgesLength = t.edgesLength();
System.out.println("Its edges are " + edgesLength[0] + ", "
+ edgesLength[1] + ", " + edgesLength[2] + " long");
} catch (Exception e) {
System.out.println("Error in the arguments of the command line");
return;
}
}
}
/**
* Triangle.java
*
* (c) DIT-UC3M 2008
*
*/
public class Triangle {
/** Vertexes of the triangle */
private Point vertex1;
private Point vertex2;
private Point vertex3;
/** Constructor of a triangle with their vertexes */
public Triangle(Point vertex1, Point vertex2, Point vertex3) {
this.vertex1 = vertex1;
this.vertex2 = vertex2;
this.vertex3 = vertex3;
}
/** Returns an array with the length of every edge of the triangle */
public double[] edgesLength() {
double edgesLength[] = new double[3];
// Length 1->2
edgesLength[0] = vertex1.distance(vertex2);
// Length 2->3
edgesLength[1] = vertex2.distance(vertex3);
// Length 3->1
edgesLength[2] = vertex3.distance(vertex1);
return edgesLength;
}
}
In this execise, we are going to create a Date
class that will allow us to work with dates. This class has to store some attributes and must define some methods that will make different basic operations.
Before start writing the code, try to think about the design of Date
class.
What kind of information must be stored in each object? If some given data can be stored in different formats, would you use several attributes to represent the same information? Why? Which format do you think is more appropriate?
What constructors would you provide? Notice that constructors have to initialize the internal object data.
Think of what methods you think would be useful to be included in the class.
Can you think of any kind of information that could be suitable to be included in the class and that is common for
all objects from Date
?
Define all attributes for Date
class.
The Date
class has to provide two constructors to initialize Date
's objects.
A constructor with three integers that represent the day, month and year, respectively.
A constructor with three strings of characters that represent the day, month and year, respectively.
Object attributes should be declared with private access to avoid making errors in their updates.
Program both get
and set
methods which are necesary to read and update encapsulated
information of Date
's objects.
toString()
method for a text representation of the object.The toString()
method has a special meaning for all objects in Java. It is used to get a String representation of the object that shows the values of the object's attributes at a given moment.
Program the toString()
method according to the following declaration:
public String toString() { /* completar */ }
This method has to return a string of characters with a text representation of a date, according to the following format (don't worry about the ordinal ("21st", "13th"):
month(text) day(number), year(number)
EXAMPLE : August 6, 2007
compareTo()
method to compare dates.The compareTo()
method has a special meaning for objects in Java. It is used to compare two objects.
RECOMMENDED READING: Consult the Java API documentation of the comparation interface at the following link Comparable. In this page, look for what value must be returned in each case of comparation of the two objects.
Program the compareTo()
method according to the following declaration:
public int compareTo(Date date) {
/* ... */
}
This method compares the date stored in the current object with the date stored in the other object that is passed as input parameter and it must return:
-1 if the date stored in the current object is previous than the date stored in the object passed as parameter.
0 if both dates are equal.
1 if the date stored in the current object is later than the date stored in the object passed as parameter.
Remember that a class can contain several methods with the same name, as long as they have distinct input parameters. This is known as method overloading.
Program an auxiliary method that returns the number of days that the month that is passed by parameter has. Overload that method so that it can be used with either the number or the name of the month. Both methods have the following declarations:
... int getDaysInMonth(int month) {
/* complete */
}
... int getDaysInMonth(String month) {
/* complete */
}
The solution of these exercises are included in the following listings:
import java.io.*;
public class Date {
/**
* Months of the year in order, to facilitate the conversion to integer format
*
* The number of the month is the same as the position of the name of the
* month in this array plus 1. (because the positions in the array start in 0,
* but months start in 1)
*/
private static final String[] months = { "January", "February", "March",
"April", "May", "June", "July", "August", "September", "October",
"November", "December" };
// ATTRIBUTES
private int day;
private int month;
private int year;
// CONSTRUCTORS
public Date(int day, int month, int year) throws ExceptionDate {
checkDate(day, month, year);
this.day = day;
this.month = month;
this.year = year;
}
public Date(String sDay, String sMonthName, String sYear)
throws ExceptionDate {
// Convert strings to number
try {
day = Integer.parseInt(sDay);
year = Integer.parseInt(sYear);
} catch (NumberFormatException nfe) {
// Error converting a string to a number
throw new ExceptionDate("Wrong date");
}
month = getMonth(sMonthName);
// Checking that values have sense
checkDate(day, month, year);
}
// ACCESORS
public int getDay() {
return day;
}
public int getMonth() {
return month;
}
public int getYear() {
return year;
}
public void setDay(int day) throws ExceptionDate {
checkDate(day, this.month, this.year);
this.day = day;
}
public void setMonth(int month) throws ExceptionDate {
checkDate(this.day, month, this.year);
this.month = month;
}
public void setYear(int year) throws ExceptionDate {
checkDate(day, month, year);
this.year = year;
}
// METHODS
public String toString() {
return (day + " of " + months[month - 1] + ", " + year);
}
public int compareTo(Date date) {
int result = 0;
if (year < date.getYear()) {
result = -1;
} else if (year > date.getYear()) {
result = 1;
} else { // Years are the same => compare the months
if (month < date.getMonth()) {
result = -1;
} else if (month > date.getMonth()) {
result = 1;
} else { // Months are the same => compare the days
if (day < date.getDay()) {
result = -1;
} else if (day > date.getDay()) {
result = 1;
} else { // Days are also the same => same date
result = 0;
}
}
}
return result;
}
// AUXILIAR METHODS
/**
* Returns the number of the days of a given month
*/
private int getDaysFromMonth(int month) throws ExceptionDate {
int monthDays = 0;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12: // months of 31 days
monthDays = 31;
break;
case 4:
case 6:
case 9:
case 11: // months of 30 days
monthDays = 30;
break;
case 2: // February
if (isLeapYear(year))
monthDays = 29;
else
monthDays = 28;
break;
default: // Wrong month
throw new ExceptionDate("Wrong month");
}
return monthDays;
}
/**
* Returns the number of days of a given month
*/
private int getDaysFromMonth(String month) throws ExceptionDate {
return getDaysFromMonth(getMonth(month));
}
/**
* Auxiliary method to get the number of a month, given its name. It returns
* -1 if the text does not refers to any month.
*/
private static int getMonth(String sMonthName) throws ExceptionDate {
// Get the number of the month
int month = -1;
for (int i = 0; i < months.length && month == 0; i++) {
if (months[i].equalsIgnoreCase(sMonthName)) {
// The month referes to this element in the array
month = i + 1;
}
}
return month;
}
/**
* Auxiliary method to check if a date is valid or not
*/
private void checkDate(int day, int month, int year) throws ExceptionDate {
// Check that the day is valid
// (The getMonthDay already checks if the month is valid)
if ((day <= 0) || (day > getDaysFromMonth(month))) {
throw new ExceptionDate("Wrong date");
}
}
/**
* Checks if a year is a leap year A year is leap year if it is multiple of 4
* and not multiple of 100, and the multiple of 400.
*/
private boolean isLeapYear(int year) {
return ((((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0));
}
public static Date readDate() {
BufferedReader entry = new BufferedReader(new InputStreamReader(System.in));
Date date = null;
String sDay, sMonth, sYear; // Variables to store the entry of the user
int iMonth;
boolean correct = false;
do {
try {
System.out.print("Enter day: ");
System.out.flush();
sDay = entry.readLine();
System.out.print("Enter month: ");
System.out.flush();
sMonth = entry.readLine();
System.out.print("Enter year: ");
System.out.flush();
sYear = entry.readLine();
// Check if the user has entered the name of the month
iMonth = getMonth(sMonth);
if (iMonth == -1) {
// Check if the user has entered the number of the month
iMonth = Integer.parseInt(sMonth);
}
date = new Date(sDay, months[iMonth], sYear);
correct = true;
} catch (Exception ex) {
correct = false;
}
} while (!correct);
return date;
}
public Date moreRecentDate(Date[] dates) {
Date date = null;
if ((dates != null) && (dates.length > 0)) {
int max = 0;
for (int i = 1; i < dates.length; i++) {
if (dates[max].compareTo(dates[i]) < 0) {
max = i;
}
}
date = dates[max];
}
return date;
}
}
/**
* Exception ExceptionDate is thrown when a Date object is created with wrong
* data.
*/
public class ExceptionDate extends Exception {
/**
* Default constructor, creates an exception without a descriptive message.
*/
public ExceptionDate() {
super(); // invoke the constructor of the base class Exception
}
/**
* Constructor with parameters, it creates an exception with a descriptive
* message of the error.
*
* @param message
* descriptive message of the error that creates the exception.
*/
public ExceptionDate(String message) {
super(message); // invoke the constructor of the base class Exception
}
}
Review class declaration and object creation.
The Album
class represents the production of a singer or musical groups. This class has the following attributes:
title
: The Album title
author
: The name of the singer or group
year
: Publishing year
elements
: Number of CDs or DVDs included in the Album
price
: Suggested retail price (without VAT)
genre
: A character indicating the type of genre (D: Dance, P: Pop, R: Rock, C: Classical, J: Jazz, O: Other)
isSpanish
: True if it is an album of a Spanish singer or group
Think about the attributes, their data type and modifiers. Then implement the Album class in Java
Then implement a new class called AlbumTest
that only contains the main
method to test the Album
class. This class has to:
Create two objects of type Album
called album1
and album2
Assign a value to the attributes with data from two albums that you like
Print the information of each album correctly tabulated as shown below
Album:
Title: Crazy Hits
Author: Crazy Frog
Year: 2005
Num: 1
Price: 14.99
Genre: D
Is Spanish?: False
The solution is included in the following listings:
public class Album { public String title; public String author; public int year; public int elements; public float price; public char genre; public boolean isSpanish; public void printAlbum() { System.out.println("Album:"); System.out.println("Title:\t\t" + title); System.out.println("Author:\t\t" + author); System.out.println("Year:\t\t" + year); System.out.println("Price:\t\t" + price + " euros"); System.out.println("Genre:\t\t" + genre); System.out.println("IsSpanish:\t" + isSpanish); System.out.println(""); // Might also be made by calling the access methods: // System.out.println("Title:\t\t"+getTitle()); // ... } }
Album.java
public class AlbumTest { public static void main(String[] args) { Album album1; Album album2; // Object creation album1 = new Album(); album2 = new Album(); // assigning value to the attributes album1.title = "Crazy Hits"; album1.author = "Crazy Frog"; album1.year = 2005; album1.elements = 1; album1.price = 14.99f; album1.genre = 'D'; // album1.isSpanish=false; album2.title = "Cien gaviotas donde iran"; album2.author = "Varios"; album2.year = 2005; album2.elements = 1; album2.price = 14.99f; album2.genre = 'O'; album2.isSpanish = true; // printing information about album1 and album2 album1.printAlbum(); album2.printAlbum(); } }
AlbumTest.java
Review objects encapsulation and access to private attributes using public methods.
Add the necessary get
and set
to assign and retrieve the value of each attribute. For the genre
attribute, check that the character used is valid before assigning it.
Modify the main
method of AlbumTest
to use the access method defined above. Check the result.
The solution is included in the following listing:
public class Album { private String title; private String author; private int year; private int elements; private float price; private char genre; private boolean isSpanish; public void setTitle(String title) { this.title = title; } public void setAuthor(String author) { this.author = author; } public void setYear(int year) { this.year = year; } public void setElements(int elements) { this.elements = elements; } public void setPrice(float price) { this.price = price; } public void setGenre(char genre) { switch (genre) { case 'D': case 'P': case 'R': case 'C': case 'J': case 'O': this.genre = genre; break; default: System.out .println("The genre is not valid use one of the following characters: \n DANCE: D \n POP: P \n ROCK: R \n CLASSICAL: C \n JAZZ: J \n OTHER: O"); } } public void setIsSpanish(boolean isSpanish) { this.isSpanish = isSpanish; } public String getTitle() { return title; } public String getAuthor() { return author; } public int getYear() { return year; } public int getElements() { return elements; } public float getPrice() { return price; } public char getGenre() { return genre; } public boolean getIsSpanish() { return isSpanish; } public void printAlbum() { System.out.println("Album:"); System.out.println("Title:\t\t" + title); System.out.println("Author:\t\t" + author); System.out.println("Year:\t\t" + year); System.out.println("Price:\t\t" + price + " euros"); System.out.println("Genre:\t\t" + genre); System.out.println("IsSpanish:\t" + isSpanish); System.out.println(""); // Might also be made by calling the access methods: // System.out.println("Title:\t\t"+getTitle()); // ... } }
Album.java
public class AlbumTest { public static void main(String[] args) { Album album1; Album album2; // Object creation album1 = new Album(); album2 = new Album(); // assigning value to the attributes album1.setTitle("Crazy Hits"); album1.setAuthor("Crazy Frog"); album1.setYear(2005); album1.setElements(1); album1.setPrice(14.99f); album1.setGenre('D'); album1.setIsSpanish(false); album2.setTitle("Cien gaviotas donde iran"); album2.setAuthor("Varios"); album2.setYear(2005); album2.setElements(1); album2.setPrice(14.99f); album2.setGenre('O'); album2.setIsSpanish(true); // printing information about album1 and album2 album1.printAlbum(); album2.printAlbum(); } }
AlbumTest.java
Review arithmetic operators.
Modify AlbumTest.java
to calculate the total price of the albums (with and without VAT) and print a message on the screen like this:
Total price (without VAT): 29.98 euros
Total price (with 16% VAT): 34.7768 euros
The solution is included in the following listing:
public class AlbumTest { public static void main(String[] args) { Album album1; Album album2; // Object creation album1 = new Album(); album2 = new Album(); // assigning value to the attributes album1.setTitle("Crazy Hits"); album1.setAuthor("Crazy Frog"); album1.setYear(2005); album1.setElements(1); album1.setPrice(14.99f); album1.setGenre('D'); album1.setIsSpanish(false); album2.setTitle("Cien gaviotas donde iran"); album2.setAuthor("Varios"); album2.setYear(2005); album2.setElements(1); album2.setPrice(14.99f); album2.setGenre('O'); album2.setIsSpanish(true); // printing information about album1 and album2 album1.printAlbum(); album2.printAlbum(); System.out.println("Total price (without IVA): " + (album1.getPrice() + album2.getPrice())); System.out.println("Total price (with 16% IVA): " + (1.16 * (album1.getPrice() + album2.getPrice()))); } }
AlbumTest.java
Review constructors and their relationship to access methods.
We have not written any constructor for the Album
class yet. After creating an object of Album
class, we have to call access methods such as setTitle
or setAuthor
for assigning value to the attributes of the newly created object. As you know from past labs, this has the disadvantage that you can forget to give value to an attribute and this would result in the creation of objects with inconsistent values. In order to solve this problem you must implement a constructor method to assign value to the attributes when an object is created. To do this, you have to pass a set of parameters to the constructor. This allows us to call the constructor as follows:
new Album("Crazy Hits","Crazy Frog",2005,1,14.99,'D',false);
The solution is included in the following listing:
public class Album { private String title; private String author; private int year; private int elements; private float price; private char genre; private boolean isSpanish; public Album(String title, String author, int year, int elements, float price, char genre, boolean isSpanish) { setTitle(title); setAuthor(author); setYear(year); setElements(elements); setPrice(price); setGenre(genre); setIsSpanish(isSpanish); // In some cases, when there is no verification of data before making the // assignment // you can asign value directly in the constructor instead of calling the // Set method // this.title = title; // ... } public void setTitle(String title) { this.title = title; } public void setAuthor(String author) { this.author = author; } public void setYear(int year) { this.year = year; } public void setElements(int elements) { this.elements = elements; } public void setPrice(float price) { this.price = price; } public void setGenre(char genre) { switch (genre) { case 'D': case 'P': case 'R': case 'C': case 'J': case 'O': this.genre = genre; break; default: System.out .println("The genre is not valid use one of the following characters: \n DANCE: D \n POP: P \n ROCK: R \n CLASSICAL: C \n JAZZ: J \n OTHER: O"); } } public void setIsSpanish(boolean isSpanish) { this.isSpanish = isSpanish; } public String getTitle() { return title; } public String getAuthor() { return author; } public int getYear() { return year; } public int getElements() { return elements; } public float getPrice() { return price; } public char getGenre() { return genre; } public boolean getIsSpanish() { return isSpanish; } public void printAlbum() { System.out.println("Album:"); System.out.println("Title:\t\t" + title); System.out.println("Author:\t\t" + author); System.out.println("Year:\t\t" + year); System.out.println("Price:\t\t" + price + " euros"); System.out.println("Genre:\t\t" + genre); System.out.println("IsSpanish:\t" + isSpanish); System.out.println(""); // Might also be made by calling the access methods: // System.out.println("Title:\t\t"+getTitle()); // ... } }
Album.java
public class AlbumTest { public static void main(String[] args) { Album album1; Album album2; // Object creation album1 = new Album("Crazy Hits", "Crazy Frog", 2005, 1, 14.99f, 'D', false); album2 = new Album("Cien gaviotas donde iran", "Varios", 2005, 1, 14.99f, 'O', true); // printing information about album1 and album2 album1.printAlbum(); album2.printAlbum(); System.out.println("Total price (without IVA): " + (album1.getPrice() + album2.getPrice())); System.out.println("Total price (with 16% IVA): " + (1.16 * (album1.getPrice() + album2.getPrice()))); } }
AlbumTest.java
Review the use of constants and the switch selection statement.
Create constants to represent each different musical genre and assign its corresponding value, for instance, ROCK='R'
. Modify the setGenre
method so as to use these constants when the code checks the valid genres and assigns the value to the genre
attribute.
The solution is included in the following listing:
public class Album { public static final char DANCE = 'D'; public static final char POP = 'P'; public static final char ROCK = 'R'; public static final char CLASSICAL = 'C'; public static final char JAZZ = 'J'; public static final char OTHER = 'O'; private String title; private String author; private int year; private int elements; private float price; private char genre; private boolean isSpanish; public Album(String title, String author, int year, int elements, float price, char genre, boolean isSpanish) { setTitle(title); setAuthor(author); setYear(year); setElements(elements); setPrice(price); setGenre(genre); setIsSpanish(isSpanish); // In some cases, when there is no verification of data before making the // assignment // you can asign value directly in the constructor instead of calling the // Set method // this.title = title; // ... } public void setTitle(String title) { this.title = title; } public void setAuthor(String author) { this.author = author; } public void setYear(int year) { this.year = year; } public void setElements(int elements) { this.elements = elements; } public void setPrice(float price) { this.price = price; } public void setGenre(char genre) { switch (genre) { case DANCE: case POP: case ROCK: case CLASSICAL: case JAZZ: case OTHER: this.genre = genre; break; default: System.out .println("The genre is not valid use one of the following characters: \n DANCE: D \n POP: P \n ROCK: R \n CLASSICAL: C \n JAZZ: J \n OTHER: O"); } } public void setIsSpanish(boolean isSpanish) { this.isSpanish = isSpanish; } public String getTitle() { return title; } public String getAuthor() { return author; } public int getYear() { return year; } public int getElements() { return elements; } public float getPrice() { return price; } public char getGenre() { return genre; } public boolean getIsSpanish() { return isSpanish; } public void printAlbum() { System.out.println("Album:"); System.out.println("Title:\t\t" + title); System.out.println("Author:\t\t" + author); System.out.println("Year:\t\t" + year); System.out.println("Price:\t\t" + price + " euros"); System.out.println("Genre:\t\t" + genre); System.out.println("IsSpanish:\t" + isSpanish); System.out.println(""); // Might also be made by calling the access methods: // System.out.println("Title:\t\t"+getTitle()); // ... } }
Album.java
Review the use of classes as reference types in attribute declaration.
The album's price is something that could be changed depending on our pricing policies, seasonal offers, etc. We are going to change the price
attribute in order to get a better management of these changes. Instead of using a basic type (double) we are going to create a new type called Rate
. Thus we can declare a Rate
class to encapsulate a set of data and specific behaviour that allows to calculate the album's price.
Implement a Rate
class with the following information:
3 constants to represent different prices (NORMAL=0, REDUCED=1, INCREASED=2)
A base
attribute to represent the basic price without offers or surcharges
A plus
attribute to represent the amount that will be added or subtracted to/from the basic price
A getPrice
method that calculates the price using the following formula and returns its value:
Normal price = base*num
Reduced price (eg. seasonal offers) = base*num*(1-plus)
Increased price (eg. special edition) = base*num*(1+plus)
The solution is included in the following listing:
public class Album { public static final char DANCE = 'D'; public static final char POP = 'P'; public static final char ROCK = 'R'; public static final char CLASSICAL = 'C'; public static final char JAZZ = 'J'; public static final char OTHER = 'O'; private String title; private String author; private int year; private int elements; private Rate rate; private char genre; private boolean isSpanish; public Album(String title, String author, int year, int elements, float price, char genre, boolean isSpanish) { setTitle(title); setAuthor(author); setYear(year); setElements(elements); setPrice(price); setGenre(genre); setIsSpanish(isSpanish); // In some cases, when there is no verification of data before making the // assignment // you can asign value directly in the constructor instead of calling the // Set method // this.title = title; // ... } public Album(String title, String author, int year, int elements, float price, float plus, char genre, boolean isSpanish) { setTitle(title); setAuthor(author); setYear(year); setElements(elements); setPrice(price, plus); setGenre(genre); setIsSpanish(isSpanish); // In some cases, when there is no verification of data before making the // assignment // you can asign value directly in the constructor instead of calling the // Set method // this.title = title; // ... } public Album(String title, String author, int year, int elements, float price, float plus, int rateType, char genre, boolean isSpanish) { setTitle(title); setAuthor(author); setYear(year); setElements(elements); setPrice(price, plus, rateType); setGenre(genre); setIsSpanish(isSpanish); // In some cases, when there is no verification of data before making the // assignment // you can asign value directly in the constructor instead of calling the // Set method // this.title = title; // ... } public void setTitle(String title) { this.title = title; } public void setAuthor(String author) { this.author = author; } public void setYear(int year) { this.year = year; } public void setElements(int elements) { this.elements = elements; } public void setPrice(float base) { rate = new Rate(base); } public void setPrice(float base, float plus) { rate = new Rate(base, plus); } public void setPrice(float base, float plus, int rateType) { rate = new Rate(base, plus, rateType); } public void setGenre(char genre) { switch (genre) { case DANCE: case POP: case ROCK: case CLASSICAL: case JAZZ: case OTHER: this.genre = genre; break; default: System.out .println("The genre is not valid use one of the following characters: \n DANCE: D \n POP: P \n ROCK: R \n CLASSICAL: C \n JAZZ: J \n OTHER: O"); } } public void setIsSpanish(boolean isSpanish) { this.isSpanish = isSpanish; } public String getTitle() { return title; } public String getAuthor() { return author; } public int getYear() { return year; } public int getElements() { return elements; } public float getPrice() { float resultado = 0; resultado = (rate.getPrice()) * elements; return resultado; } public char getGenre() { return genre; } public boolean getIsSpanish() { return isSpanish; } public int getRateType() { int resultado = rate.getRateType(); return resultado; } public void printAlbum() { System.out.println("Album:"); System.out.println("Title:\t\t" + title); System.out.println("Author:\t\t" + author); System.out.println("Year:\t\t" + year); System.out.println("Price:\t\t" + getPrice() + " euros"); System.out.println("Genre:\t\t" + genre); System.out.println("IsSpanish:\t" + isSpanish); System.out.println("Rate type:\t" + getRateType()); System.out.println(""); // Might also be made by calling the access methods: // System.out.println("Title:\t\t"+getTitle()); // ... } }
Album.java
public class AlbumTest { public static void main(String[] args) { Album album1; Album album2; Album album3; // Object creation album1 = new Album("Crazy Hits", "Crazy Frog", 2005, 1, 14.99f, 0.1f, 1, 'D', false); album2 = new Album("Cien gaviotas donde iran", "Varios", 2005, 1, 14.99f, 0.1f, 2, 'O', true); album3 = new Album("Prueba", "Varios", 2005, 1, 14.99f, 0.1f, 0, 'O', true); // printing information about album1 and album2 album1.printAlbum(); album2.printAlbum(); album3.printAlbum(); System.out.println("Total price (without IVA): " + (album1.getPrice() + album2.getPrice() + album3.getPrice())); System.out.println("Total price (with 16% IVA): " + (1.16 * (album1.getPrice() + album2.getPrice() + album3.getPrice()))); } }
AlbumTest.java
public class Rate{ private static final int NORMAL = 0; private static final int REDUCED = 1; private static final int INCREASED = 2; private int rateType; private float base; private float plus; public Rate(float base){ this.base = base; this.plus = 10; setRateType(0); } public Rate(float base, float plus){ this.base = base; this.plus = plus; setRateType(0); } public Rate(float base, float plus, int rateType){ this.base = base; this.plus = plus; setRateType(rateType); } public void setRateType(int rateType){ if (rateType==NORMAL || rateType == REDUCED || rateType == INCREASED){ this.rateType=rateType; }else{ this.rateType=-1; System.out.println("The rate type is not valid use one of the following values: \n NORMAL: 0 \n REDUCED: 1 \n INCREASED: 2 \n "); } } public float getPrice(){ float resultado = 0; switch(rateType){ case NORMAL: resultado = base; break; case REDUCED: resultado = base*(1+plus); break; case INCREASED: resultado = base*(1-plus); break; } return resultado; } public int getRateType(){ return rateType; } }
Rate.java