Reputation: 10777
I have a problem about implementing a 1 to 1 association in java. For example, conside the following class diagram:
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
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
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
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
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