简体   繁体   中英

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:

在此输入图像描述

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.

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();
  }

}

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.

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 .

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

While the Interface Segregation Principle can sometimes be helpful, and some people scoff at the idea of interfaces which don't promise that all implementations will support all members, I would suggest that it may be helpful to have Student and Employee interfaces which include isStudent and isEmployee members, and then have Person implement both interfaces; some methods like giveRaise() shouldn't work on someone who isn't an employee, but others like getOutstandingPay() should work just fine (if someone hasn't earned any money, the method should simply return zero).

While it may seem ugly to complicate all Person objects with methods that won't be applicable for many of them, such a design avoids difficulties in the event that a student gets hired, or an employee starts taking classes. Having separate classes for Student , Employee , and StudentEmployee , even if one could do so easily, would require that a Student who got a job be replaced with a new object instance in order to become a StudentEmployee . By contrast, if one has a Person class whose instances may or may not be able to handle methods like giveRaise , then one can handle situations where objects' abilities change during their lifetimes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM