yrazlik
yrazlik

Reputation: 10777

Implementing 1 to 1 classes in java

I have a problem about implementing a 1 to 1 association in java. For example, conside the following class diagram:

enter image description here

I implement it like this:

public class Student{
    private AttendanceRole attendance;

    public Student(AttendanceRole attendance){
        this.attendance=attendance;
        addTwoWayLink(this); //creates the two-way link between objects
    }

    public void setAttendanceRole(AttendanceRole a){ //if a students changes from 
        attendance = a;                              //part time to full time
    } 

}

public class AttendanceRole{
    private Student student;

    void addTwoWayLink(Student student){
        this.student=student;
    }

}

Here is the problem:

1) Assume i created a student object and i want to change the attendance role of a student. In this case, i call setAttendanceRole method. But i have to give it an AttendanceRole object as a parameter. Since this is a 1 to 1 relationship, the parameter i give also has a student associated with it. So, this is a problem. Also i can't create an AttendanceRole object without a link to a student since this is a 1 to 1 association. The same situation occurse when i first try to create a student object and call its constructor. I can give null as parameter value, but in this case don't i harm the 1 to 1 relationship constraint? What can i do about it?

2)Also, i design this class so that we can create a student object and set its AttendanceRole. I mean we cannot create an AttendanceRole object and set its student. Is this a bad idea? Or is it up to designer which object will be created first.

Thank you

Upvotes: 0

Views: 2002

Answers (4)

Raedwald
Raedwald

Reputation: 48644

As it is impossible for a simple setAttendanceRole(AttendanceRole a) method to satisfy the constraint, your Student class must not have such a method.

As it is impossible to create an AttendanceRole that satisfies the constraint, it must not be possible to independently create such an object. (Yes, really). As an AttendanceRole and Student are so intimately connected, they are not really entirely separate classes.

Constaints (invariants) must apply only on return from accessible methods. Private methods and constructors need not satisfy them. Consider making AttendanceRole a nested class of Student, and using factory functions instead of public constructors for Student.

 public class Student {
      public abstract class AttendanceRole {
         ...

         public final Student getStudent() {
            return Student.this;
         }
      }

      private final class FullTimeStudent extends AttendanceRole {
         ...
      }

      private AttendanceRole role;

      private Student() {
         ...
         // this.role is null
      }

      public static Student createFullTimeStudent() {
         final Student s = new Student();
         s.role = new FullTimeStudent();
         return s;
      }

      public final AttendanceRole getRole() {
         return role;
      }

The AttendanceRole.getStudent() method gets hold of the outer-class object using the special syntax Student.this.

Upvotes: 1

Apurv
Apurv

Reputation: 3753

I would suggest you design something like below

public interface AttendanceRole {
}

public class FullTimeStudent implements AttendanceRole {
}

public class PartTimeStudent implements AttendanceRole {
}

public class Student {
    private AttendanceRole attendaceRole;
    public AttendanceRole  getAttendanceRole(){
        return attendaceRole;
    }
    public void setAttendaceRole(AttendaceRole attendaceRole)}
        this.attendaceRole = attendaceRole;
    }
}

When you create Student object, pass corresponding Attendance Role (Full Time/Part Time).

Code sample creating Student objects:

Student student1 = new Student();
Student student2 = new Student();
FullTimeStudent fullTimeStudent = new FullTimeStudent ();
PartTimeStudent partTimeStudent = new PartTimeStudent ();
student1.setAttendanceRole(fullTimeStudent );
student2.setAttendanceRole(partTimeStudent );

Upvotes: 1

Jim
Jim

Reputation: 469

What exactly do you want to accomplish ?

You could try this with an enum like the answer of Capt. Skyhawk.

Or you could try with inheritance:

public abstract class Student{

   public void methodA() { ... }


   public void methodB();

}

public class FullTimeStudent extends Student {

   public void methodB(){ //fulltime implementation }

}

public class PartTimeStudent extends Student {


   public void methodB(){ //parttime implementation }


}

Upvotes: 2

Captain Skyhawk
Captain Skyhawk

Reputation: 3500

Try rearranging your classes:

public enum ROLE_TYPE { FULL_TIME, PART_TIME }

public class student {

    private ROLE_TYPE attendanceRole;

    public SetRoleType( ROLE_TYPE type )
    {
        this.attendanceRole = type;
    }

    public GetRoleType()
    {
        return attendanceRole;
    }
}

Upvotes: 3

Related Questions