0

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

yrazlik
  • 10,411
  • 33
  • 99
  • 165

4 Answers4

3

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;
    }
}
Captain Skyhawk
  • 3,499
  • 2
  • 25
  • 39
2

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 }


}
Jim
  • 469
  • 1
  • 3
  • 13
  • actually i want to implement the class diagram given in the picture. In your code, fulltime and parttime students are subclasses of student, but this is not the case in the picture. I want to implement the exact situation in the picture – yrazlik Apr 24 '13 at 12:51
  • Take a look at [the answer](http://stackoverflow.com/a/16192399/2239110) given by Apurv. – Jim Apr 24 '13 at 12:56
1

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 );
Apurv
  • 3,723
  • 3
  • 30
  • 51
  • Thanks, but doesn't the same problem occur in the setter method? Can you show how can i implement setter method in that design? – yrazlik Apr 24 '13 at 12:50
1

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.

Community
  • 1
  • 1
Raedwald
  • 46,613
  • 43
  • 151
  • 237