Solution: Interface or abstract class
To implement the problem, my choice was to extend an abstract superclass Employee:

UML class diagram: inheritance of abstract class Employee
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:
- abstract class Employee // abstract class
- {
- private static int cntID = 1000; // reuseable code
- protected int ID;
- protected String name;
- protected String occupation;
- protected String workPlace;
- public Employee() { }
- public Employee(String name, String occupation, String workplace)
- {
- ID = ++cntID;
- this.name = name;
- this.occupation = occupation;
- this.workPlace = workplace;
- }
- public int getID()
- {
- return ID;
- }
- public String getName()
- {
- return name;
- }
- public String getOccupation()
- {
- return occupation;
- }
- public abstract String determineWorkPlace(); // only this has to be implemented by subclasses
- }
The concrete subclass FulltimeEmployee takes over every attribute and member, only the abstract method determineWorkPlace() of superclass Employee has to be defined:
- class FulltimeEmployee : Employee
- {
- public FulltimeEmployee(String name, String occupation, String workplace)
- : base(name, occupation, workplace)
- { }
- public override String determineWorkPlace() // Method has to be implemented by subclass
- {
- return workPlace;
- }
- }
The second concrete subclass Apprentice has to define the method determineWorkPlace() too. The method getOccupation() is overridden for demonstration purposes:
- class Apprentice : Employee
- {
- private List<DateRange> dateRanges; // apprentice visits vocational school
- public Apprentice(String name, String occupation, String workplace, List<DateRange> dateRanges)
- : base(name, occupation, workplace)
- {
- this.dateRanges = dateRanges;
- }
- // method is overridden for demonstration purposes
- public String getOccupation()
- {
- return "apprentice " + occupation;
- }
- public override String determineWorkPlace() // has to be implemented by subclass
- {
- DateTime now = DateTime.Now; // today
- foreach (DateRange dateRange in dateRanges)
- if (dateRange.Includes(now))
- return "vocational school";
- return workPlace;
- }
- }
For avoiding code dublication the two objects of subclasses of Employee are assigned to an List of type Employee. It can be iterated by a foreach loop:
- class Program
- {
- static void Main(string[] args)
- {
- Apprentice apprentice = new Apprentice("apprentice", "developer", "R101",
- new List<DateRange> {
- new DateRange(new DateTime(2019, 8, 12), new DateTime(2019, 8, 30)),
- new DateRange(new DateTime(2019, 11, 11), new DateTime(2019, 11, 29))
- });
- FulltimeEmployee fulltimeEmployee = new FulltimeEmployee("full-time employee", "developer", "R102");
- // no repeating of code by the use of loop
- List<Employee> employees = new List<Employee> { apprentice, fulltimeEmployee };
- foreach (Employee employee in employees)
- {
- Console.WriteLine("ID: " + employee.getID()
- + "\tName: " + employee.getName()
- + "\tOccupation: " + employee.getOccupation()
- + "\tWorkplace: "
- + employee.determineWorkPlace()
- );
- }
- Console.ReadKey();
- }
- }
The output in case of actual date is in range of vocational school block will be:
ID: 1001 Name: apprentice Occupation: apprentice developer Workplace: vocational school
ID: 1002 Name: full-time employee Occupation: developer Workplace: R102
The additional helperclass is shown below:
- class DateRange
- {
- public DateRange(DateTime start, DateTime end)
- {
- Start = start;
- End = end;
- }
- public DateTime Start { get; private set; }
- public DateTime End { get; private set; }
- public bool Includes(DateTime value)
- {
- return (Start <= value) && (value <= End);
- }
- }