Let’s begin by modeling the products that our vending machine will sell.
For this purpose we will define a new ProductDetail
class. Each product will have a unique productCode
to identify it, a price
, and a name
:
public final class ProductDetail {
private final String productCode;
private final double price;
private final String name;
public ProductDetail(String productCode, double price, String name) {
this.productCode = productCode;
this.price = price;
this.name = name;
}
public String getProductCode() {
return productCode;
}
public double getPrice() {
return price;
}
public String getName() {
return name;
}
}
Using an Immutable Class
As you may have noticed, we have made our class final
, as well as all of our attributes.
As explained in Chapter 5, a final
class can’t be extended by other classes, and when an attribute is final
, its value can only be initialized in the constructor and can’t be changed afterwards.
By having the class and all fields as final
, our class becomes an immutable class in which we can’t change its state after the object was created.
We have made our class immutable for it to work correctly when stored in a HashSet
. Remember that objects that don’t comply with the equals
and hashCode
contracts can cause problems as described in the Hash Tables introduction. In the next section, our product catalog uses a HashSet
hence why we’re doing this up-front.
Using a Set
will allow us to avoid having multiple items in our vending machine with the same productCode
. To achieve this, we have to override the equals
and hashCode
methods to only depend on the productCode
attribute:
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (!(o instanceof ProductDetail)) {
return false;
}
return ((ProductDetail) o).getProductCode().equals(this.productCode);
}
@Override
public int hashCode() {
return productCode.hashCode();
}