COMP1405 - Assignment #4 - WordPress.com

59 downloads 3100 Views 124KB Size Report
Here is how you can do this (dates are discussed in chapter 12 of the notes): GregorianCalendar aCalendar = new GregorianCalendar(); // makes today's date .
COMP1405 - Assignment #4 (Due: Friday, November 27th @ 4:30pm (afternoon)) In this assignment, you will build a very simple insurance company system. You will gain practice with inheritance, overriding methods, an abstract class, abstract methods and Exceptions. You will also make use of proper coding style by making public/private/protected attributes & methods and creating get/set methods. The insurance system will keep track of the insurance company's clients. Each client will have at least one policy with the company. The assignment constructs the system in three parts: defining insurance policies, defining clients and defining an Exception. Here is a diagram showing these classes: Object

Client

IndividualClient

CompanyClient

Policy

DepreciablePolicy

ExpirablePolicy

(1) The Policy Class Define a public class called Policy which has a private static/class variable called NEXT_POLICY_NUMBER which is an int (initially set to 1) representing the number to be given to the next policy created. Create the following attributes in the class as well: • •

a private attribute called policyNumber of type int that identifies the policy with a unique integer. a protected attribute called amount that contains the amount (a float) of coverage for the policy.

Create a public constructor which takes a single float parameter and uses it to set the amount variable. The constructor sets the policyNumber such that each created policy has a unique number and also updates the class variable appropriately. Create public get methods for your attributes as well as a public toString() method that returns a String with the following format (use String.format() for both the policy number and amount) : Policy: 0001 amount: $320.00

Create a public instance method called isExpired() which always returns false. Now test your code with this program: public class PolicyTestProgram { public static void main(String args[]) { System.out.println(new Policy(320)); // displays System.out.println(new Policy(500.1f)); // displays System.out.println(new Policy(0)); // displays System.out.println(new Policy(320).isExpired()); // } }

Policy: 0001 amount: $320.00 Policy: 0002 amount: $500.10 Policy: 0003 amount: $0.00 displays false

(2) The DepreciablePolicy Class Now we will make some subclasses to represent different types of policies. Define a public class called DepreciablePolicy as a subclass of Policy which has a private attribute called rate of type float which represents the rate at which the policy depreciates each time a claim is made. For example, a rate of 0.10 means that the value of the policy (i.e., the amount) depreciates 10% each time a claim is made (we will discuss the making of claims in the next section). Implement these: •

a public constructor which takes a float representing the amount and another float representing the rate. This constructor should use inheritance by calling the constructor from the superclass to set the amount and policyNumber.



a public get method for the rate.



a public toString() method that returns a String with the following format: DepreciablePolicy: 0001 amount: $320.00 rate: 10.0%

You MUST make use of inheritance by calling the toString() from the superclass (You will have to make a change to the Policy class’ toString() method as well. In addition, you will need to make the amount attribute from Policy to be protected now). Also, use String.format() again to display the rate. •

an instance method called isExpired() which returns true if the amount of this policy has depreciated to 0. You should be able to write this method WITHOUT any IF statements … try.



an instance method called depreciate() which reduces the amount of the policy by the rate percentage. For example, if the amount is $100 and the rate is 0.10, then the amount after this method is called once should be $90.

(3) The ExpirablePolicy Class Define a ExpirablePolicy class as a subclass of Policy which has a private attribute called expiryDate of type Date that contains the date after which the policy is invalid. The Date class is in the java.util package, so import java.util.* at the top of your code. Implement these: •

a public constructor which takes a float representing the amount and a Date representing the expiryDate. This constructor should use inheritance by calling the constructor from the superclass to set the amount and policyNumber.



a public constructor which takes a float representing the amount. This constructor should use inheritance by calling the constructor from the superclass to set the amount and policyNumber. The expiryDate should then be set to exactly one year after the policy was created. Here is how you can do this (dates are discussed in chapter 12 of the notes): GregorianCalendar aCalendar = new GregorianCalendar(); aCalendar.add(Calendar.YEAR,1); expiryDate = aCalendar.getTime();

// makes today’s date



a public get method for the expiryDate.



a toString() method that returns a String with the following format: ExpirablePolicy: 0001 amount: $320.00 expires: April 30, 2001

You MUST make use of inheritance by calling the toString() from the superclass. Note that to display a date in the format above (i.e., April 30, 2001), you can use String.format() again with a format string of "%1$tb %1$te,%1$tY" for the date part. •

an instance method called isExpired() which returns true if the computer's current date is ON or AFTER the expiryDate and false otherwise. (Hint: the Date class has methods before(Date d) and after(Date d)). Also, new Date() returns today’s date.

Now test your new classes with this test program: import java.util.*; public class PolicyTestProgram2 { public static void main(String args[]) { DepreciablePolicy p1; ExpirablePolicy p2, p3; // Make sure that the Policy toString() method still works System.out.println(new Policy(320)); // Make a DepreciablePolicy p1 = new DepreciablePolicy(500.1f, 0.1f); System.out.println(p1); // Now depreciate it a little p1.depreciate(); System.out.println(p1); // Make an Expirable Policy System.out.println(new ExpirablePolicy(1000)); // Make another Expirable Policy p2 = new ExpirablePolicy(2000, new GregorianCalendar(2025, 0, 2).getTime()); System.out.println(p2); System.out.println(p2.isExpired()); // Make yet another Expirable Policy p3 = new ExpirablePolicy(2500, new GregorianCalendar(1997, 3, 1).getTime()); System.out.println(p3); System.out.println(p3.isExpired()); } }

Here is the output (assuming that today’s date is before the year 2025) Policy: 0001 amount: $320.00 DepreciablePolicy: 0002 amount: $500.10 rate: 10.0% DepreciablePolicy: 0002 amount: $450.09 rate: 10.0% ExpirablePolicy: 0003 amount: $1000.00 expires: May 28,2010 ExpirablePolicy: 0004 amount: $2000.00 expires: Jan 2,2025 false ExpirablePolicy: 0005 amount: $2500.00 expires: Apr 1,1997 true

(4) The Client class Define a public class called Client which has a private static/class variable called NEXT_ID which is an int (initially set to 1) representing the number to be given to the next client created. Add the following attributes to the class as well: •

a private attribute called id of type int that identifies the client with a unique integer.



a private attribute called name of type String that represents the client's name.



a protected attribute called policies of type ArrayList that contains the client’s policies.

Implement the following in the Client class: •

a public constructor which takes a single String parameter and uses it to set the name variable. The constructor sets the id such that each created client has a unique number and also updates the class variable appropriately. It should also set the policies list to a new empty list.



a public set method for the name attribute and public get methods for all 3 attributes.



a public toString() method with the following format:



a public method called totalCoverage() which returns a float containing the total amount of coverage of all the client's policies.



a public method called openPolicyFor(float amt) which creates a new Policy for the amount specified in the parameter, adds it to the ArrayList of policies and returns the new Policy object.



a public method called openPolicyFor(float amt, float rate) which creates a new DepreciablePolicy for the amount and rate specified in the parameters, adds it to the ArrayList of policies and returns the new DepreciablePolicy object.



a public method called openPolicyFor(float amt, Date expire) which creates a new ExpirablePolicy for the amount and expiry date specified in the parameters, adds it to the ArrayList of policies and returns the new ExpirablePolicy object. Notice that these 3 open methods are examples of overloading.



a public method called getPolicy(int polNum) which examines all Policy objects in policies. If one is found whose policyNumber matches the input parameter then it is returned by the method. Otherwise null is returned.



a public method called cancelPolicy(int polNum) which uses the getPolicy() method above to determine the policy that is to be cancelled. If one is found then it is removed from the policies list and returned by the method. Otherwise null is returned.

Client 0001: John Smith

Now test what you have done so far with this program: import java.util.*; public class ClientTestProgram { public static void main(String args[]) { Client c = new Client("Bob B. Pins"); System.out.println(c); c.openPolicyFor(100); c.openPolicyFor(200, 0.10f); c.openPolicyFor(300, new GregorianCalendar(2005, 0, 2).getTime()); System.out.println(c.getPolicies()); System.out.println(c.totalCoverage()); System.out.println(c.cancelPolicy(6)); System.out.println(c.cancelPolicy(1)); System.out.println(c.totalCoverage()); } }

Here is the output: Client 0001: Bob B. Pins [Policy: 0001 amount: $100.00, DepreciablePolicy: 0002 amount: $200.00 rate: 10.0%, ExpirablePolicy: 0003 amount: $300.00 expires: January 2, 2005] 600.0 null Policy: 0001 amount: $100.00 500.0

Now make the Client class abstract. Try running the test code above again but WITHOUT recompiling. Do you know what InstantiationError means ? Think about it ... and then try recompiling your test code. Now do you understand what happened ?

(5) The IndividualClient and CompanyClient Subclasses Now create two subclasses of Client, one called IndividualClient and the other called CompanyClient. Do not implement any attributes or methods yet for these classes. Try compiling them. Notice that your test code will not compile. That's because subclasses DO NOT inherit constructors and java requires a constructor to be available. You will have to create a constructor (taking a single String argument) for each of these subclasses that calls the one in Client explicitly. Alter your ClientTestProgram by changing the first line to be: CompanyClient c = new CompanyClient("Bob B. Pins");

Re-run the test. Go back and change your toString() method in Client so that the proper client type is displayed. For example: CompanyClient 0001: Bob B. Pins Now define a public abstract method in the Client class called makeClaim(int polNum) that returns a float. After re-compiling the Client class, try recompiling the IndividualClient and CompanyClient classes. Do you understand the error message ?

Implement the makeClaim(int polNum) method in the IndividualClient class as follows. First check to make sure that the policy with the given number has not expired. If it has, then return 0. IndividualClients are allowed to make only 1 claim per for regular policies but Depreciable Policies and Expirable Policies can have multiple claims. So, if the Policy with the given number is of type Policy, you should remove the policy from the policies list after making this claim (make use of the cancelPolicy() method to do this). (Be careful if you use the instanceof keyword ... are subclasses of Policy instances of Policy ?) If the claim is being made for a DepreciablePolicy, then you must make sure to depreciate the policy. For IndividualClients, you should depreciate the policy BEFORE returning the claim amount. This method should return the amount of the policy if the policy was indeed valid, otherwise 0 is returned. We will now write a similar method in the CompanyClient class. However, we will make use of the double dispatching technique. Before we do this, we will have to go write a method called handleClaim() in each of the policy classes so that we can make use of them here. •

In the Policy class, implement handleClaim() so that it returns the amount of the claim.



In the DepreciablePolicy class, implement handleClaim() so that it returns the amount of the claim but also depreciates the claim. Note that the amount returned is BEFORE depreciating (note that this is the opposite from IndividualClients which depreciated after the amount was returned).



In the ExpirablePolicy class, implement handleClaim() so that it returns the amount of the claim as long as the policy has not yet expired, otherwise it returns 0.

Now go back to the CompanyClient class and implement the makeClaim(int polNum) method so that it first checks to make sure the policy number is valid and then uses the double-dispatching technique by calling the handleClaim() method. Note that you MUST NOT use any IF statements to determine the policy type ... as that would undo the advantages of double-dispatching. Test your code with the following program: import java.util.*; public class ClientTestProgram2 { public static void main(String args[]) { // Create an individual client, open some policies // and then make some claims IndividualClient ic = new IndividualClient("Bob B. Pins"); ic.openPolicyFor(100); ic.openPolicyFor(200, 0.10f); ic.openPolicyFor(300, new GregorianCalendar(2025, 0, 2).getTime()); ic.openPolicyFor(400, new GregorianCalendar(1999, 5, 4).getTime()); Policy p = new Policy(500); System.out.println("Here are the Individual Client's policies:"); System.out.println(ic.getPolicies()); System.out.println("Making claims:"); System.out.println("Claim for policy 0001: " + ic.makeClaim(1)); System.out.println("Claim for policy 0002: " + ic.makeClaim(2)); System.out.println("Claim for policy 0003: " + ic.makeClaim(3)); System.out.println("Claim for policy 0004: " + ic.makeClaim(4)); System.out.println("Claim for policy 0005: " + ic.makeClaim(5)); System.out.println("Here are the Individual Client's policies after claims:"); System.out.println(ic.getPolicies()); // Create a company client, open some policies // and then make some claims CompanyClient cc = new CompanyClient("The Pillow Factory"); cc.openPolicyFor(1000); cc.openPolicyFor(2000, 0.10f);

cc.openPolicyFor(3000, new GregorianCalendar(2025, 0, 2).getTime()); cc.openPolicyFor(4000, new GregorianCalendar(1999, 5, 4).getTime()); System.out.println("\nHere are the Company Client's policies:"); System.out.println(cc.getPolicies()); System.out.println("Making claims:"); System.out.println("Claim for policy 0006: " + cc.makeClaim(6)); System.out.println("Claim for policy 0007: " + cc.makeClaim(7)); System.out.println("Claim for policy 0008: " + cc.makeClaim(8)); System.out.println("Claim for policy 0009: " + cc.makeClaim(9)); System.out.println("Claim for policy 0005: " + cc.makeClaim(5)); System.out.println("Here are the Company Client's policies after claims:"); System.out.println(cc.getPolicies()); } }

Here is the expected output: Here are the Individual Client's policies: [Policy: 0001 amount: $100.00, DepreciablePolicy: 0002 amount: $200.00 rate: 10.0%, ExpirablePolicy: 0003 amount: $300.00 expires: Jan 2,2025, ExpirablePolicy: 0004 amount: $400.00 expires: Jun 4,1999] Making claims: Claim for policy 0001: 100.0 Claim for policy 0002: 180.0 Claim for policy 0003: 300.0 Claim for policy 0004: 0.0 Claim for policy 0005: 0.0 Here are the Individual Client's policies after claims: [DepreciablePolicy: 0002 amount: $180.00 rate: 10.0%, ExpirablePolicy: 0003 amount: $300.00 expires: Jan 2,2025, ExpirablePolicy: 0004 amount: $400.00 expires: Jun 4,1999] Here are the Company Client's policies: [Policy: 0006 amount: $1000.00, DepreciablePolicy: 0007 amount: $2000.00 rate: 10.0%, ExpirablePolicy: 0008 amount: $3000.00 expires: Jan 2,2025, ExpirablePolicy: 0009 amount: $4000.00 expires: Jun 4,1999] Making claims: Claim for policy 0006: 1000.0 Claim for policy 0007: 2000.0 Claim for policy 0008: 3000.0 Claim for policy 0009: 0.0 Claim for policy 0005: 0.0 Here are the Company Client's policies after claims: [Policy: 0006 amount: $1000.00, DepreciablePolicy: 0007 amount: $1800.00 rate: 10.0%, ExpirablePolicy: 0008 amount: $3000.00 expires: Jan 2,2025, ExpirablePolicy: 0009 amount: $4000.00 expires: Jun 4,1999]

(6) Adding an Exception Create a subclass of Exception called PolicyNotFoundException. Create a constructor that takes a String as a parameter and calls the superclass constructor that also takes a String (as we did in the notes). You do not need to create any other methods for this class. Go back to your method in the Client class called getPolicy() and modify it so that instead of returning null when the policy is not found, a PolicyNotFoundException is thrown. When calling the exception's constructor, pass in a String of this format: "Bad Policy Number 0001" (where 0001 is the number of the policy being searched for). Note that you will be forced to declare that the method throws this new exception.

Try recompiling the Client class. Notice that any method which calls the getPolicy() method must now handle the exception (e.g., cancelPolicy()). Make changes to the cancelPolicy() method so that it also declares that it throws the exception. Now your Client code should compile. You will have to go back into your makeClaim() method (i.e., in the CompanyClient and IndividualClient classes) to also handle the exception. DO NOT have your makeClaim() method throw any exceptions. Instead, handle the exception in the makeClaim() method directly by displaying the exception's message and returning 0. Simplify your method code, since you no longer have to check for null from the getPolicy() or cancelPolicy() methods. Make changes to your ClientTestProgram so that it handles the PolicyNotFoundException each time the cancelPolicy() method is called. You should catch the exception and simply display its message (which you can obtain by sending getMessage() to the exception parameter). Here is the output that you should get … notice the exception's message being shown: CompanyClient: 0001 Bob B. Pins [Policy: 0001 amount: $100.00, DepreciablePolicy: 0002 amount: $200.00 rate: 10.0%, ExpirablePolicy: 0003 amount: $300.00 expires: Jan 2,2005] 600.0 Bad Policy Number: 6 Policy: 0001 amount: $100.00 500.0

Here is the output from the ClientTestProgram2 after these exception changes: Here are the Individual Client's policies: [Policy: 0001 amount: $100.00, DepreciablePolicy: 0002 amount: $200.00 rate: 10.0%, ExpirablePolicy: 0003 amount: $300.00 expires: Jan 2,2025, ExpirablePolicy: 0004 amount: $400.00 expires: Jun 4,1999] Making claims: Claim for policy 0001: 100.0 Claim for policy 0002: 180.0 Claim for policy 0003: 300.0 Claim for policy 0004: 0.0 Bad Policy Number: 5 Claim for policy 0005: 0.0 Here are the Individual Client's policies after claims: [DepreciablePolicy: 0002 amount: $180.00 rate: 10.0%, ExpirablePolicy: 0003 amount: $300.00 expires: Jan 2,2025, ExpirablePolicy: 0004 amount: $400.00 expires: Jun 4,1999] Here are the Company Client's policies: [Policy: 0006 amount: $1000.00, DepreciablePolicy: 0007 amount: $2000.00 rate: 10.0%, ExpirablePolicy: 0008 amount: $3000.00 expires: Jan 2,2025, ExpirablePolicy: 0009 amount: $4000.00 expires: Jun 4,1999] Making claims: Claim for policy 0006: 1000.0 Claim for policy 0007: 2000.0 Claim for policy 0008: 3000.0 Claim for policy 0009: 0.0 Bad Policy Number: 5 Claim for policy 0005: 0.0 Here are the Company Client's policies after claims: [Policy: 0006 amount: $1000.00, DepreciablePolicy: 0007 amount: $1800.00 rate: 10.0%, ExpirablePolicy: 0008 amount: $3000.00 expires: Jan 2,2025, ExpirablePolicy: 0009 amount: $4000.00 expires: Jun 4,1999]

NOTE: For each coding question, submit your .java and your compiled .class files as well as any necessary .txt files. Submit your assignment using WebCT. Note that if your internet connection at home is down or does not work, we will not accept this as a reason for handing in an assignment late ... so make sure to submit the assignment WELL BEFORE it is due !