What you really want to do here is use composition and not inheritance. Keep all your objects as type Student, and then temporarily assign the behaviour of a TutorRole as it is required to each instance of Student.
With this design your Student class will contain a property (member variable) of type TutorRole that you can add or remove at runtime. Adding an isTutor() method will allow you to detemine whether a Student is a Tutor at runtime in a clear and concise manner.
The TutorRole class will encapsulate the behaviour (i.e. methods) of being a Tutor.
/*
* The TutorRole can be set at runtime
*/
public class Student {
private String facultyId;
private TutorRole tutorRole = null;
public boolean isTutor() {
return !(tutorRole == null);
}
public void doTutorStuff() {
if(isTutor()) {
tutorRole.doTutorStuff();
}
else {
throw new NotTutorException();
}
}
public void setTutorRole(TutorRole tutorRole) {
this.tutorRole = tutorRole;
}
}
/*
* Ideally this class should implement a generic interface, but I'll keep this simple
*/
public class TutorRole {
public void doTutorStuff() {
// implementation here
}
}
/*
* Now let's use our classes...
*/
Student st = new Student(); // not a tutor
st.setTutorRole(new TutorRole()); // now a tutor
if(st.isTutor()) {
st.doTutorStuff();
}
st.setTutorRole(null); // not a tutor anymore
An alternative approach is to have a Tutor class contain a reference to a Student object, but it depends on how you are going to be interacting with the Student and Tutor objects on which way around you want to code this.
You could just write a method like TutorToStudent() on Tutor and create a new Student from your Tutor. If you cast you'll end up with the object still being a Tutor.
You might also consider forgoing inheritence in this case and just have a flag indicating the whether or not this student is a Tutor.