Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inherit from two classes

I have a People class, and Student and Employee classes which inherit from it. But if I have a person who is both a Student and an Employee...

... How would you go about implementing this?

like image 775
Sihan Wang Avatar asked Jan 26 '15 17:01

Sihan Wang


2 Answers

That's a classic example of an improperly analyzed problem domain. Yes, in some situations, it may be proper to think of "Student" as a type of "Person" and an "Employee" as a type of "Person", but - depending on your problem domain - it may also not be appropriate.

If your domain requires that something be both a "Student" and an "Employee", you should consider if the relation between "Student" and "Person" in your problem domain is really an "is-a" relationship.

It could be that in this particular case, being a student is merely an attribute of a particular person. So, John Doe is a person, who may also have a "current occupation" of "Student". In this case, he may have a list of several "current occupations". And the relationship in such a world becomes "has-a" rather than "is-a". So "Student" and "Employee" become subclasses of "Occupation".

like image 161
RealSkeptic Avatar answered Nov 15 '22 14:11

RealSkeptic


As per the comment:

it is a interview question, i think you can make any assumption here

If this is the case, the only correct answer is to describe your assumptions, and how you address them.

If you strictly adhere to the requirements, you could make Student and Employee interfaces and have different classes implement them:

public interface Student {
    void learn();
}

public interface Employee {
    void work();
}

public class Person {
    // properties, getters and setters for name, age, sex, etc.
}

public class StudentPerson extends Person implements Student {
    @Override
    public void learn() {}
}

public class EmployeePerson extends Person implements Employee {
    @Override
    public void work() {}
}
public class StudentEmployeePerson extends Person implements Student, Employee {
    @Override
    public void work();

    @Override
    public void learn() {}
}

Taking this an extra mile would be to extract the logic of work() and learn() to helper classes, and have StudentPerson, EmployeePerson and StudentEmployeePerson call them respectively.

But this, IMHO, missed the point of the exercise.

A student who also has a job is still a student. He cannot be a separate class from a student who doesn't.

I'd create a Role interface, have Student and Employee implement it, and allow a Person to have multiple Roles, so he can be both a student and an employee:

public interface Role {
    void perform();
}

public class Student implements Role {
    @Override
    void perform() { /* go study */ }
}

public class Employee implements Role {
    @Override
    void perform() { /* go work */ }
}

public class Person {
    // properties, getters and setters for name, age, sex, etc.

    private Set<Role> roles = /* initialized somehow */

    public void doStuff() {
        for (Role role : roles) {
            role.perform();
        }
    }
}

EDIT:
To answer the question in the comment, a person who is both a student and an employee would be constructed by adding Roles. For simplicity's sake the snippet below assumes that these classes have constructors from the relevant properties, and that Person has methods to add and remove the Roles to the internal set:

Person person = new Person("John Doe", 21, Sex.Male);
person.addRole(new Student("Stack Overflow University"));
person.addRole(new Employee("Secret Government Spy"));
like image 32
Mureinik Avatar answered Nov 15 '22 13:11

Mureinik