0
\$\begingroup\$

I am discussing with one of my peers about proper encapsulation. We had to write this code. One of the specifications is: "The Student object has to have a Grade object called finalGrade. Code hint: Grade finalGrade;"

This is my code

public class Student
{
  private String firstName;
  private String lastName;
  private String id;

  public Grade finalGrade = new Grade(); // THIS IS THE QUESTIONABLE CODE
...
...
}

public class TestStudent
{

  public static void main(String[] args)
  {
   ...
   ...
   ...
    student.finalGrade.setGradeValue(85);   
    student.finalGrade.setLetterGrade('B');
    student.setFinalGrade('B');

    System.out.println(student.finalGrade.getGradeValue()); 
    System.out.println(student.finalGrade.getLetterGrade());
  }
}

This is their code

public class Student {
...
Grade finalGrade;  // THIS IS THE QUESTIONABLE CODE
public Grade getFinalGrade() {
return finalGrade;
}

public void setFinalGrade(Grade finalGrade) {
this.finalGrade = finalGrade;
}

....
public String toString() {
String display = String.format("Student: id= %d name= %s letterGrade = %s", ID, getName(), finalGrade );
return display;
}
}

public class TestStudent {
public static void main(String[] argv) {
...
...
Grade g = new Grade();
g.setGradeValue(85);
g.setLetterGrade('B');
s.setFinalGrade(g);
System.out.println(s.toString());
}
}

Ultimately, which code is better given the specification? My argument is that finalGrade is a class and should be accessed with the dot operator. My peer states that it is an attribute and should be private. I see it as a class accessing a class such as SuperClass.class.method();

\$\endgroup\$

closed as off-topic by Phrancis, alecxe, Graipher, 200_success Mar 23 '17 at 11:12

This question appears to be off-topic. The users who voted to close gave this specific reason:

If this question can be reworded to fit the rules in the help center, please edit the question.

2
\$\begingroup\$

One of the most important concept of Object Oriented Programming (and programming in general) is information hiding and encapsulation. A class should never expose its attributes unless there are some very valid reasons to do so (for example to share a constant). The fields of a class should be made available providing getters and setters. The reasons of that are many. For example if you have that field finalGrade public and a day you will want to change some details of that field, e.g. use a subclass of Grade, you will cause a long cascade of errors wherever you made a reference to that object without a getter method. We could spend a lot of time talking about how information hiding is important in OOP, but in short...your peer is right!

\$\endgroup\$
  • \$\begingroup\$ Okay, thank you. I am just slightly confused when you mentioned "Change some details of that field e.g. use a subclass of Grade" \$\endgroup\$ – asmcriminal Mar 23 '17 at 1:24
  • \$\begingroup\$ That's mean that if you keep that field private, you could do inside the Student class private Grade finalGrade = new SubclassOfGrade; without causing errors in the others client classes. \$\endgroup\$ – ceccoemi Mar 23 '17 at 8:48
0
\$\begingroup\$

I would say that the object itself should be instantiated as private but certain methods within that object can be public. You could always create a getter for the object if you need it in another class too.

\$\endgroup\$
0
\$\begingroup\$

I am discussing with one of my peers about proper encapsulation.

proper encapsulation means no other class has access to or knows about the internal data handling of an object, Therefore any instance variable in a class should be private.

As @NathanHoy answered you may add getter methods, but you should do this with care. If your class is a data transfer object (without any business logic beside simple validation) getters (and less often setters) are useful.

In other classes you should avoid getters/setters. If some other class needs to change a property of such "business logic class" there should be mutator methods.

eg: instead of

public void setFinalGrade(Grade finalGrade) {
   this.finalGrade = finalGrade;
}

there should be a method:

public void  passedExsamWith(Grade finalGrade){
   this.finalGrade = finalGrade;
}

The difference is that the name of the second version is taken from the problem domain, not from the technical solution.

A different example may be clearer:

class Vehicle{
   private int speedInMph =0;
   public void accellerateBy(int speedDifferenceInMph){
      speedInMph +=speedDifferenceInMph;
      if (VMAX > speedInMph)
         speedInMph=VMAX);
   }
   public void deccellerateBy(int speedDifferenceInMph){
      if(speedInMph> speedDifferenceInMph)
         speedInMph -=speedDifferenceInMph;
      else
         speedInMph =0;
    }
}

Ultimately, which code is better given the specification?

Both meet this requirement (in the more or less same improper way).

My argument is that finalGrade is a class and should be accessed with the dot operator. My peer states that it is an attribute and should be private.

Your peers argument is right although she didn't made it private neither.


I see it as a class accessing a class such as SuperClass.class.method();

Solutions in the JVM itself may not always reflect a proper way to solve something. Rather stick to good readings Like "Clean Code" written by Robert C Martin" then to the examples from the JVM.


I do not fully understand the problem domain and the technical solution that you mentioned. I do see the code and understand it. I am just trying to understand the difference between the 2.

Thought that would be easy:

setFinalGrade()

is a direct reference to how the Student class deals with the Grade object. There is no reference to the problem domain of how to manage Students. In particular it does not convey why or when the student should get a Grade object.

In contrast

passedExsamWith(Grade finalGrade)

does make some sense in the context of the problem domain. It conveys the information that the student has to do an exam first before she can get a Grade object. It does not tell anything about what the Student object is supposed to do with this Grade object.

In particular: What if the requirement changes

Also, you said that my peer did not make Grade finalGrade; private either. I noticed that but I tried to access it in main and I was not able to. I tried Grade blah = Student.finalGrade; Eclipse told me to change the member to static.

Eclipse complained because you tried to access finalGrade in a static way, eg:

 Studen.finalGrade; 

This has nothing to do with the visibility scopes. This has to do with the understanding of the difference between a class and its static members and an instance of a class (aka object) and its non static members in Java.

Rule of thumb is: for any member variable (regardless if it is static or not) place a private, Only if the member is static and final it may get a different visibility scope if needed. For the others create getters/setters if the class is for DTOs (without business logic) or you have a really good reason why some other class should access this particular member directly.

\$\endgroup\$
  • \$\begingroup\$ Thank you, I do not fully understand the problem domain and the technical solution that you mentioned. I do see the code and understand it. I am just trying to understand the difference between the 2. Also, you said that my peer did not make Grade finalGrade; private either. I noticed that but I tried to access it in main and I was not able to. I tried Grade blah = Student.finalGrade; Eclipse told me to change the member to static. That also confuses me a bit. Can you elaborate on these 2 questions? \$\endgroup\$ – asmcriminal Mar 23 '17 at 1:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.