最近我接受了一次采访,我被问到以下问题。给定以下类/接口结构:
问题:
如何实现接口EmployedStudent
以重用StudentImpl
和EmployeeImpl
中的代码。
我建议将员工和学生组合到我的实施中。
根据采访者的反应,我认为他们认为这不是最好的解决方案。我花了很多时间思考它,但我无法想出另一个解决方案。
答案 0 :(得分:5)
创建一个实现Employee
和Student
的类。在您的课程中,创建EmployeeImpl
和StudentImpl
的实例。使您的类将所有方法调用委托给其中一个对象。
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();
}
}
答案 1 :(得分:3)
因此,你可以让implements Employee, Student
在内部委托给EmployeeImpl和StudentImpl,但也可以从一个实现类继承。
现在, 名称 类EmployedStudent(不是StudyingEmployee或BothEmployeeAndStudent)建议:
class EmployedStudent extends StudentImpl implements Employee {
Employee asEmployee = new EmployeeImpl();
是的,因为只委托给另一个班级,效率会更高一些。
然而,用例远非现实:所有类型的组合都可以想到几个类。在这种情况下,您的解决方案更具普遍性真正普遍,是一种查找机制:
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
}
这是能力查找。它通常可以通过使用游泳,飞行,驾驶等功能取代繁琐的继承等级,例如Vehicle,RoadVehicle,SwimmingVehicle(船),FlyingVehicle(飞机),WaterAirplane(?),AmphibianTank(?)。
不同之处在于整个脱钩。
答案 2 :(得分:1)
由于java不支持多重继承,你可以/应该
这些字段随后由&#34;我们的&#34;实施各自的方法。
答案 3 :(得分:1)
使用Java 8,您可以将代码移动到界面本身。这解决了“多重继承”问题。
答案 4 :(得分:1)
虽然接口隔离原则有时可能会有所帮助,但有些人嘲笑接口的概念并不承诺所有实现都支持所有成员,我建议Student
可能会有所帮助和Employee
接口,包括isStudent
和isEmployee
成员,然后Person
实现两个接口;像giveRaise()
这样的某些方法不适用于非员工的人,但getOutstandingPay()
之类的其他方法应该可以正常工作(如果有人没有赚到钱,该方法应该只返回零)
虽然使用不适用于其中许多对象的方法使所有Person
对象复杂化似乎很难看,但这样的设计避免了在学生被雇用或员工开始上课的情况下的困难。为Student
,Employee
和StudentEmployee
设置单独的类,即使可以轻松完成,也需要将Student
的工作替换为新对象实例以成为StudentEmployee
。相比之下,如果有一个Person
类,其实例可能或可能无法处理giveRaise
之类的方法,那么可以处理对象的能力在其生命周期内发生变化的情况。