vedran
vedran

Reputation: 2188

Java, is it possible to 'convert' object from subclass to object from superclass

I have two classes Student and Tutor. Tutor is basically a student (Tutor extends Student) who has facultyID. Once his contract is complete, he returns to being just a student. So can I somehow convert him back to his "previous" roll of student?

Upvotes: 8

Views: 6474

Answers (8)

Brad
Brad

Reputation: 15909

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.

Upvotes: 5

Lycha
Lycha

Reputation: 10187

You can't change objects type in Java. Probably the easiest way to achieve youw way is to clone all parameters from Tutor into a new Student object.

Upvotes: 1

Alexander Pogrebnyak
Alexander Pogrebnyak

Reputation: 45606

I think, this screams containment and interface programming.

How about this:

interface IStudent
{
  String getName();
  int getStudentId();
}

interface IFacultyMember
{
  int getFacultyId( );
}

class Student
  implements IStudent
{
  String name;
  int id;

  public String getName( ) { return name; }
  public int getStudentId( ) { return id; }
}

class Tutor
  implements IStudent, IFacultyMember
{
  Student student;
  int facultyId;

  public Tutor ( Student student, int facultyId )
  {
    this.student = student;
    this.facultyId = facultyId;
  }

  public String getName( ) { return student.getName( ); }
  public int getStudentId( ) { return student.getStudentId( ); }
  public int getFacultyId( ) { return facultyId; };
}

This way, your Student remains a student, even if it moves to the Tutor position. When Tutor's term expires you just GC the tutor record.

Student's record, on the other hand will still be available in Central Services.

Upvotes: 4

Desmond Zhou
Desmond Zhou

Reputation: 1409

  1. You can create a new Student with the exact same information as the Tutor and discard the original object. Either with a copy-constructor Student(Student original) or a Student toStudent() method This is the quick and dirty way.

  2. Instead of making Tutor directly extend a Student, making the Tutor specific data and behavior into a Decorator. Or better yet, make both Tutor and Student decorators of a People object that includes everyone. This is one of the proper ways to do this.

  3. Make the Tutor and Student into a enum Type and hold this field in People, this is easier but less extensible than the above, it really depend on the nature of the differences between Tutor and Student.

Upvotes: 1

jayunit100
jayunit100

Reputation: 17650

There is no such thing as "converting" him back to a student, he is a tutor, and a tutor already IS a student.

However, there may be some value in genericizing the access of this object, so that you only use student method. There are several idioms in java for this.

1) You can use the Student API exclusively in your code, with the exception of the Tutor portion.

2) You can have a "toStudent/toTutor" method for your objects, which allow them to return objects which are specific to the role.

//My preference 3) You can use interfaces. Have Tutor and Student both be interfaces, and build your objects using interface implementation. If you refer to objects using minimal interfaces, rather than heavyweight inheritance patterns, your code will probably scale better in the future.

Upvotes: 1

Ian Dallas
Ian Dallas

Reputation: 12741

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.

Upvotes: 1

G_H
G_H

Reputation: 12019

Once you create an instance of some type (for example, Tutor), that's the runtime type that instance is gonna have. This can't be changed anymore.

Some alternatives:

  • Give Student some constructor that accepts another Student instance and copies over the relevant fields. A so-called copy constructor. That way, you could easily create a new Student instance based on your Tutor and then use that instead.
  • If it's important that the actual instance is kept rather than creating some copy (maybe you've kept references all over the place), it'd be best to separate role from class. Make some FacultyMember class or something and turn Student and Tutor into roles. Then you can change the role of a FacultyMember later on.

Upvotes: 3

StriplingWarrior
StriplingWarrior

Reputation: 156728

You can cast the Tutor as a Student so your code treats him as such at compile time, but the object will remain a Tutor, so calling any overridden methods will cause the Tutor class's version to be called.

The only way to do the kind of "conversion" you're looking for is to create a new Student object and give it all the properties that the Tutor has.

Since you're finding that you need to do this conversion, you may want to re-think the class structure. For example, maybe both Students and Tutors should really just be Persons, and each Person can have the Role of Student or Teacher.

Upvotes: 2

Related Questions