Skip to main content

Interfaces

The Aims​

Banks have a variety of different products, not all of which are accounts. We want to provide an interface which forces classes which are products to have a method called getDetails(). This method will display the name and balance for account objects, but for insurance products, it will display price and amount insured information. We will need to define a further class called HomeInsurance, which has three instance variables, premium, excess, and amount insured.

We will then define an interface called Detailable, which contains the method, getDetails(). This will then be implemented in our Account classes and HomeInsurance class.

class3

We will then be able to create an array of Detailable objects, and call getDetails() on each one.

Defining the HomeInsurance class​

  1. Define a class called HomeInsurance which has properties of appropriate types, called name, premium, excess, and amount insured.

  2. Provide an appropriate constructor for your new class.

  3. Provide any other appropriate methods for your class.

Click here to see the sample solution

public class HomeInsurance {
private String name;
private double premium;
private double excess;
private double amountInsured;

public HomeInsurance() {
this.name = "Default Home";
this.premium = 1000.0;
this.excess = 500.0;
this.amountInsured = 200000.0;
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPremium() {
return premium;
}
public void setPremium(double premium) {
this.premium = premium;
}
public double getExcess() {
return excess;
}
public void setExcess(double excess) {
this.excess = excess;
}
public double getAmountInsured() {
return amountInsured;
}
public void setAmountInsured(double amountInsured) {
this.amountInsured = amountInsured;
}

@Override
public String toString() {
return "HomeInsurance [name=" + name + ", premium=" + premium + ", excess=" + excess + ", amountInsured="
+ amountInsured + "]";
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
long temp;
temp = Double.doubleToLongBits(premium);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(excess);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(amountInsured);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
HomeInsurance other = (HomeInsurance) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (Double.doubleToLongBits(premium) != Double.doubleToLongBits(other.premium))
return false;
if (Double.doubleToLongBits(excess) != Double.doubleToLongBits(other.excess))
return false;
if (Double.doubleToLongBits(amountInsured) != Double.doubleToLongBits(other.amountInsured))
return false;
return true;
}


}

Define your Interface​

  1. Create a new Interface called Detailable.

  2. In the interface, declare a method with the signature String getDetails().

Click here to see the sample solution

public interface Detailable {

String getDetails();
}

Implement the Interface​

  1. Within your class HomeInsurance, add the implements Detailable to the class declaration. This will induce an error as you have not provided the method implementation for getDetails.

  2. Hover over the error and select the quick fix option Add UnImplemented Methods. This will then add the getDetails method for you.

  3. Update the new method to return the information about the policy. To concatenate the numeric values together as a String, you can place an empty String at the start of your concatenation, something like:

return "" + premium + " " + excess;

This initial empty String promotes all the values to a String.

  1. Now implement the interface within class Account. Remember, Account is an abstract class, so therefore you now have a choice. You can either implement the interface method in Account, or in the individual subclasses. In our model, it would be best to put the method getDetails() inside Account, because the method content will be the same for all accounts. Just use the toString method to return something appropriate

Click here to see the sample solution

public class HomeInsurance implements Detailable {

...

@Override
public String getDetails() {
return "" + premium + " " + excess;
}

}
public abstract class Account implements Detailable {

...

@Override
public String getDetails() {
return "Account Details: " + toString();
}
}

Creating an arraylist of Detailables​

  1. Create a new class with a main method called TestInterfaces.

  2. In the main method, create an arraylist of type Detailable.

  3. Add into the arraylist a CurrentAccount, SavingsAccount, a CreditCard, and a HomeInsurance object.

  4. Loop through the arraylist and call the getDetails() method.

  5. Test your code. It will use polymorphism to call the appropriate method.

Click here to see the sample solution

import java.util.ArrayList;
import java.util.List;

public class TestInterfaces {
public static void main(String[] args) throws DodgyNameException {

List<Detailable> details = new ArrayList<>();
details.add(new CheckingAccount(416, "Jimmy"));
details.add(new SavingsAccount(3000, "Noah"));
details.add(new CreditCard(-656, "Diana"));
details.add(new HomeInsurance());

for (Detailable detail : details) {
System.out.println(detail.getDetails());
}
}
}