Jordan Andrews
Jordan Andrews

Reputation: 163

The object-oriented approach to a many-to-many relationship

I'm battling at the moment in trying to understand how to approach this issue in an object-oriented way.

With a many-to-many relationship such as Students-Subjects, where each student gets a mark for a certain subject, assuming the following:

I want to be able to display all the marks for a given student. I want to display all the marks from different students for a given subject I want to be able to change any student's mark for a given subject.

I have trouble with this last one, I can't seem to think of a way to relate the classes to each other so that the marks will remain congruent when changed...

Here's what I was thinking about doing in pseudocode. Pretend we have 3 students each involved in 3 subjects (9 marks total):

Make a class for Student (String name, int studNumber)

Make a class for Subject (String name, int subNumber)

Make a class for Result(int percentageScore String grade(calculated based on
percentageScore)) 

Then have an array of arrays of Result objects, eg. [1][2] in the array will 
give the score for the student with studNumber 2 in the subject with subNumber 1.   

I feel like this isn't object-oriented? There should be some kind of acknoledgement of the relationship within the class design for subject and students. If that is indeed right, could anyone point me in the right direction? How does one do this in an object-oriented way?

Thanks a lot.

Upvotes: 4

Views: 1515

Answers (4)

user2921843
user2921843

Reputation: 1

This article makes a very compelling case for including the following structures in your design:

  • Student (incl an array of Result pointers)
  • Subject (incl an array of Result pointers)
  • Result (with all the attributes that belong to the relationship)

Though the original post was a long time ago, hope this helps someone else.

Upvotes: -2

Bartek Maraszek
Bartek Maraszek

Reputation: 1414

Both subjects and grades have a limited number of values, so I suggest using enums:

public class Example {

    public static void main(String[] args) throws IOException {
        Student s1 = new Student("John Doe");
        s1.setGrade(Subject.MATHS, Grade.B);
        s1.setGrade(Subject.PHYSICS, Grade.A);
        s1.setGrade(Subject.ENGLISH, Grade.E);

        Student s2 = new Student("Jane Smith");
        s2.setGrade(Subject.MATHS, Grade.C);
        s2.setGrade(Subject.PHYSICS, Grade.C);
        s2.setGrade(Subject.ENGLISH, Grade.A);

        // print students and their grades:
        s1.printAllGrades();
        s2.printAllGrades();

        // print every subject and its grades:
        for(Subject s : Subject.values()){
            s.printAllGrades();
        }
    }
}

enum Subject{
    MATHS, PHYSICS, ENGLISH;

    private Map<Student, Grade> grades = new HashMap<Student, Grade>();

    public void setGrade(Student student, Grade grade){
        grades.put(student, grade);
    }

    public void printAllGrades(){
        System.out.println(this);
        for(Student s : grades.keySet()){
            System.out.println(s.getName() + " : " + grades.get(s));
        }
    }
}

enum Grade{ 
    A, B, C, D, E, F
}

class Student{

    private String name;
    private Map<Subject, Grade> grades = new HashMap<Subject, Grade>();

    public Student(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }

    public void setGrade(Subject subject, Grade grade){
        grades.put(subject, grade);
        subject.setGrade(this, grade);
    }

    public Grade getGrade(Subject subject){
        return grades.get(subject);
    }

    public void printAllGrades(){
        System.out.println("Grades of " + name + ":");
        for(Subject s : grades.keySet()){
            System.out.println(s + " : " + grades.get(s));
        }
    }

}

Using the enum type is suitable to list both subjects and grades. It guarantees that only suitable values can be passed as an argument and is easily extensible - you can add a method to an enum if you wish. A simple HashMap for every student is enough to hold the mappings between subjects and grades.

You may want to read more on enums in java.

Upvotes: 1

Mustafa sabir
Mustafa sabir

Reputation: 4360

Why go with such complex class structures. You can have a simple Student class.

  class Student{

  String stuName;
  long rollNo;

  public Student(String stuName, long rollNo){
   this.stuName=stuName;
   this.rollNo=rollNo;
   }
   .
   .
   .

  }

And a Subject class. Each subject has certain students enrolled and the marks that each student has scored in that subject. Which can be represented as:-

class Subject{

String subName;
HashMap<Integer,Student> Result;

public Subject(String subName){
this.subName=subName;
Result=new HashMap<Integer,Student>();
}

//add methods to add students,modify marks, etc

public void addStudent(String name,long roll, int marks){


Result.put(marks,new Student(name,roll));

}

public int giveMarksForSubject(long roll){

//iterate Results , and check for student objects to match roll no. return key of matching student
.
.
.
}

  .
  .

}

For the part where you mentioned you want to change marks for students for certain subject. You can search the Subject object by String name in your Main method's class and then change Student's marks according to name/rollNo. You can provide methods in Subject class for implementing such functionality.

Upvotes: 2

Tomas Smagurauskas
Tomas Smagurauskas

Reputation: 706

I think the approach should be same like with database tables. You should implement some sort of a "joining class" between these 2. That class should be singleton and you should reference it in both, students and subjects. The class should have some sort of a list or a map, or something with that structure, which would contain properties: student, subject, mark. That way you could iterate through that collection by any of those properties, which should do what you need. This example How to make SQL many-to-many same-type relationship table is for databases, but I think it should give you some helpful insight.

Upvotes: 0

Related Questions