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?
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?
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".
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 Role
s, 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 Role
s. 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 Role
s 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"));
Since Java doesn't allow multiple inheritance you should define interfaces for Student
and Employee
instead of inheriting from them as base classes.
What you could do is, you can change the public class Employee
to public interface Employee
and then you can do public class Student extends People implements Employee
You will have to work like this because in java, one class can inherit only from one class at the most. Cheers.
In Java it is only possible to extend one superclass. However, Java offers interfaces and one class can extend more than one interface.
You could organize your class structure like this:
interface People
interface Student extends People
interface Employee extends People
Then your employing students could be:
class EmployingStudent implements Student, Employee
In case People
is a class that cannot be changed you can do:
interface Student
interface Employee
class EmployingStudent implements Student, Employee
So the only difference would be that Student and Employee wouldn't extend People then.