Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can a child interface reuse its parents' implementations?

Recently I had an interview and I was asked the following question. Given the following class/interface structure:

enter image description here

Question:

How can one implement interface EmployedStudent to reuse code from StudentImpl and EmployeeImpl.

I suggested to compose Employee and Student into my implementation.

Based on the interviewer's reaction I don't think they found it to be the best solution. I spent a lot of time thinking about it but I cannot come up with another solution.

like image 628
gstackoverflow Avatar asked Mar 10 '15 15:03

gstackoverflow


4 Answers

Create a class that implements both Employee and Student. In your class, create an instance of both EmployeeImpl and StudentImpl. Make your class delegate all method calls to either one of the objects then.

public class EmployedStudent implements Employee, Student {

  private EmployeeImpl employee = new EmployeeImpl();
  private StudentImpl student = new StudentImpl();

  public int getSalary() {
    return this.employee.getSalary();
  }

  public float getAverageGrade() {
    return this.student.getAverageGrade();
  }

}
like image 135
user1438038 Avatar answered Nov 19 '22 09:11

user1438038


So, you could have implements Employee, Student internally delegating to both EmployeeImpl and StudentImpl, but also inherit from one implementation class.

Now the class name EmployedStudent (not StudyingEmployee or BothEmployeeAndStudent) suggests:

class EmployedStudent extends StudentImpl implements Employee {
    Employee asEmployee = new EmployeeImpl();

Yeah, a tiny bit more efficient as only delegating to one other class.

The use-case is however far from realistic: all kind of combinations are thinkable of several classes. In that case your solution is more universal. Really universal, is a lookup-mechanism:

public class Person {
    public <T> T as(Class<T> klazz) { ... }
}

Person person = ...;
Student asStudent = person.as(Student.class);
if (asStudent != null) {
     ...
}
Employee asEmployee = person.as(Employee.class);
if (asEmployee != null) {
    asEmployee.quitJob();
    asEmployee = person.as(Employee.class); // null
}

That is a lookup of capabilities. It typically can replace a cumbersome inheritance hierarchy, say of Vehicle, RoadVehicle, SwimmingVehicle (boat), FlyingVehicle (air plane), WaterAirplane (?), AmphibianTank (?) by using capabilities Swimming, Flying, Driving.

The difference is the entire decoupling.

like image 44
Joop Eggen Avatar answered Nov 19 '22 11:11

Joop Eggen


As java doesn't support multiple inheritance, you could/should

  • either have a field for each of the wanted superclasses
  • or derive from one superclass and have a field for the other one.

The fields are then referred to by "our" implementation of the respective methods.

This is one of the design patterns from the GoF, I think it is the Proxy pattern.

like image 1
glglgl Avatar answered Nov 19 '22 10:11

glglgl


With Java 8, you can move code into the interface itself. That solves the "multiple inheritance" problem.

like image 1
Necreaux Avatar answered Nov 19 '22 09:11

Necreaux