We now modify class Employee
such that it implements interface Payable
. Figure G.25 contains the modified class, which is identical to that of Fig. G.16 with two exceptions. First, line 4 of Fig. G.25 indicates that class Employee
now implements
interface Payable
. So we must rename earnings
to getPaymentAmount
throughout the Employee
hierarchy. As with method earnings
in the version of class Employee
in Fig. G.16, however, it does not make sense to implement method getPaymentAmount
in class Employee
because we cannot calculate the earnings payment owed to a general Employee
—we must first know the specific type of Employee
. In Fig. G.16, we declared method earnings
as abstract
for this reason, so class Employee
had to be declared abstract
. This forced each Employee
concrete subclass to override earnings
with an implementation.
In Fig. G.25, we handle this situation differently. Recall that when a class implements an interface, it makes a contract with the compiler stating either that the class will implement each of the methods in the interface or that the class will be declared abstract
. If the latter option is chosen, we do not need to declare the interface methods as abstract
in the abstract
class—they’re already implicitly declared as such in the interface. Any concrete subclass of the abstract
class must implement the interface methods to fulfill the superclass’s contract with the compiler. If the subclass does not do so, it too must be declared abstract
. As indicated by the comments in lines 62–63, class Employee
of Fig. G.25 does not implement method getPaymentAmount
, so the class is declared abstract
. Each direct Employee
subclass inherits the superclass’s contract to implement method getPaymentAmount
and thus must implement this method to become a concrete class for which objects can be instantiated. A class that extends one of Employee
’s concrete subclasses will inherit an implementation of getPaymentAmount
and thus will also be a concrete class.
1 // Fig. G.25: Employee.java
2 // Employee abstract superclass that implements Payable.
3
4 public abstract class Employee implements Payable
5 {
6 private String firstName;
7 private String lastName;
8 private String socialSecurityNumber;
9
10 // three-argument constructor
11 public Employee( String first, String last, String ssn )
12 {
13 firstName = first;
14 lastName = last;
15 socialSecurityNumber = ssn;
16 } // end three-argument Employee constructor
17
18 // set first name
19 public void setFirstName( String first )
20 {
21 firstName = first; // should validate
22 } // end method setFirstName
23
24 // return first name
25 public String getFirstName()
26 {
27 return firstName;
28 } // end method getFirstName
29
30 // set last name
31 public void setLastName( String last )
32 {
33 lastName = last; // should validate
34 } // end method setLastName
35
36 // return last name
37 public String getLastName()
38 {
39 return lastName;
40 } // end method getLastName
41
42 // set social security number
43 public void setSocialSecurityNumber( String ssn )
44 {
45 socialSecurityNumber = ssn; // should validate
46 } // end method setSocialSecurityNumber
47
48 // return social security number
49 public String getSocialSecurityNumber()
50 {
51 return socialSecurityNumber;
52 } // end method getSocialSecurityNumber
53
54 // return String representation of Employee object
55 @Override
56 public String toString()
57 {
58 return String.format( "%s %s
social security number: %s",
59 getFirstName(), getLastName(), getSocialSecurityNumber() );
60 } // end method toString
61
62 // Note: We do not implement Payable method getPaymentAmount here so
63 // this class must be declared abstract to avoid a compilation error.
64 } // end abstract class Employee