To implement the problem, my choice was to extend an abstract superclass Employee:


UML class diagram: extension of an abstract classUML class diagram: inheritage of abstract class



The reason for not to choose the implementation of an interface is, that the abstract class Employee has a lot of attributes and methods which can be reused in both subclasses. The code is more compact:

 1 public abstract class Employee {                       // abstract class
 2 
 3     private static int cntID = 1000;                   // reuseable code
 4 
 5     protected int ID;
 6     protected String name;
 7     protected String occupation;
 8     protected String workPlace;
 9 
10     Employee(String name, String occupation, String workplace)
11     {
12         ID = ++cntID;
13         this.name = name;
14         this.occupation = occupation;
15         this.workPlace = workplace;
16     }
17     public int getID() {
18         return ID;
19     }
20     public String getName() {
21         return name;
22     }
23     public String getOccupation() {
24         return occupation;
25     }
26 
27     abstract protected String determineWorkPlace();  // only this has to be implemented by subclasses
28 }


The concrete subclass FulltimeEmployee takes over every attribute and member, only the abstract method determineWorkPlace() of superclass Employee has to be defined:

 1 public class FulltimeEmployee extends Employee {
 2 
 3     FulltimeEmployee(String name, String occupation, String workplace) {
 4         super(name, occupation, workplace);
 5     }
 6 
 7     public String determineWorkPlace() {        // Method has to be implemented by subclass
 8        return workPlace;
 9     }
10 }


The second concrete subclass Apprentice has to define the method determineWorkPlace() too. The method getOccupation() is overridden for demonstration purposes:

 1 import java.text.SimpleDateFormat;
 2 import java.util.ArrayList;
 3 import java.util.Date;
 4 
 5 public class Apprentice extends Employee {
 6     private ArrayList<String> daysOfVocationalSchoolInstruction;           // apprentice visits vocational school
 7 
 8     Apprentice(String name, String occupation, String workplace, ArrayList<String> daysOfVocationalSchoolInstruction) {
 9         super(name, occupation, workplace);
10         this.daysOfVocationalSchoolInstruction = daysOfVocationalSchoolInstruction;
11     }
12 
13     @Override                                       // method is overridden for demonstration purposes
14     public String getOccupation() {
15         return "apprentice " + occupation;
16     }
17 
18     public String determineWorkPlace() {            // has to be implemented by subclass
19         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("u");   // Day number of week (1 = Monday, ..., 7 = Sunday)
20         Date date = new Date();
21         if(daysOfVocationalSchoolInstruction.contains(simpleDateFormat.format(date)))
22             return "vocational school";
23         else
24             return workPlace;
25     }
26 }


For avoiding code dublication the two objects of subclasses of Employee are assigned to an ArrayList of type Employee. It can be iterated by a foreach loop:

 1 import java.util.ArrayList;
 2 import java.util.Arrays;
 3 
 4 public class Main {
 5 
 6     public static void main(String[] args) {
 7 
 8         Apprentice apprentice = new Apprentice("apprentice", "developer","E203",
 9                 new ArrayList<String>(Arrays.asList("1","2")));      // Day number of week (1 = Monday, ..., 7 = Sunday)
10 
11         FulltimeEmployee fulltimeEmployee = new FulltimeEmployee("full-time employee", "developer", "E203");
12 
13         // no repeating of code by the use of a loop
14         ArrayList<Employee> employees  = new ArrayList(Arrays.asList(apprentice, fulltimeEmployee));
15         for (Employee employee : employees) {
16             System.out.println("ID: " + employee.getID()
17                     + "\tName: " + employee.getName()
18                     + "\tOccupation: " + employee.getOccupation()
19                     + "\tWorkplace: "
20                     + employee.determineWorkPlace()
21             );
22         }
23     }
24 }


The output on monday and thuesday will be:

ID: 1001    Name: apprentice            Occupation: apprentice developer    Workplace: vocational school
ID: 1002    Name: full-time employee    Occupation: developer    Workplace: E203
Last modified: Monday, 3 June 2019, 8:43 AM