Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 787
Jordan Andrews Avatar asked Nov 19 '25 16:11

Jordan Andrews


2 Answers

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.

like image 177
Mustafa sabir Avatar answered Nov 21 '25 05:11

Mustafa sabir


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.

like image 41
Bartek Maraszek Avatar answered Nov 21 '25 04:11

Bartek Maraszek