1

Let's say i have 2 constructor classes; Person and Arm.

public class Person
{
  private Arm arm; //instance variable

  public Person(Arm arm) //Constructor
  {
    this.arm = arm;
  }
}

-

public class Arm
{
  private int fingers; //instance variable

  public Arm(int fingers) //Constructor
  {
    this.fingers = fingers;
  }

  public int getFingers()
  {
    return this.fingers();
  }

}

Every Person object has an Arm Object as an instance-variable. Every Arm object has an int instance-variable called fingers.

What is the proper way to access the fingers variable?

1. Create another getFingers() method, in the Person class:

//in Person.java
public int getFingers()
{
  return this.arm.getFingers(); //This is refrencing the getFingers() method in the Arm class
}

So i can access it like this:

Arm myArm = new Arm(5);
Person me = new Person(myArm);

System.out.println(me.getFingers());
  1. Create a method in Person that returns the arm.

    public Arm getArm()
    {
      return this.arm;
    }
    

so i can use the getFingers method from the Arm class like this:

Arm myArm = new Arm(5);
Person me = new Person(myArm);

System.out.println(me.getArm().getFingers())
8
  • 1
    This code doesn't compile; Private and Public with a capital 'P' are not proper Java keywords. Commented Jul 7, 2015 at 14:28
  • Normally I would say #2, but it really depends on what you are doing, what you are willing to expose publicly, etc.. Also, your call would be me.getArm().getFingers(), not me.myArm.getFingers() Commented Jul 7, 2015 at 14:28
  • @sstan Yes, sorry fixed :) Commented Jul 7, 2015 at 14:30
  • @RedRoboHood I'm sorry but i can't find any capital "P"s for any of the access flags in the code? Commented Jul 7, 2015 at 14:37
  • @JackPettersson Of course not. You fixed them after I posted my comment. Commented Jul 7, 2015 at 14:38

5 Answers 5

2

Normally I would suggest that the Law of Demeter comes into play here.

  • Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.
  • Each unit should only talk to its friends; don't talk to strangers.
  • Only talk to your immediate friends.

If I were to write:

A a = new A();
D d = a.getB().getC().getD();

then that would allow you to access D from an instance of A but it effectively breaks encapsulation and reveals that an A has a B, B has a C etc. etc. You might argue that this is redundant in your case, since you would expect a Person to have an Arm.

An alternative approach is to think about what you really want the top-level object (Person) to do, and tell it to do it for you. e.g. if you want the fingers so you can tell them to grasp something (perhaps) then:

person.pickUp(object)

and the person can determine how to do that itself (it could choose an arm, or it's feet or mouth in extreme situations!). Rather than get the fingers yourself, you're telling the object to do something for you. Which is really what OOP is all about.

Sign up to request clarification or add additional context in comments.

2 Comments

That makes sense, although it will clutter the Person object with a ton of methods (if i were to create more instance-objects and methods for them) hmm... I guess it depends on the remaining code. Thanks for the input!
I think it depends on that object's responsibilities, and how granular you make those
0

There is not best practice for this kind of problem.

It is depending on what you like to expose or hide to users of Person class. If you like to hide the information that Person includes an Arm add a public method getFingers() to the class Person. If there are not problems exposing the Arm class outside then add a method getArm() to the class Person.

Note that exposing Arm if there is a method setFinger() in the Arm class it is usable from any user of Person class. Exposing a method getFingers() block the possibility to directly access the method setFinger()

Comments

0

Option 1: person.getArmFingers(), useful if you do not want to expose the arm object at all and want all interaction to go through Person object. However keep in mind that every attribute you add to the arm (like hasHair :) will need to be now wrapped through Person which may not be desirable in the long run. If you want to use this consider making the Arm object package private

Option 2: Use person.getArm().getFingers(). This will expose the Arm object but will not need every arm attribute to be accessed through Person. This may not be desirable in cases where the Arm in itself has no meaning without being part of a person.

So the answer to your question: It depends

Comments

0

There is really no correct answer as it really depends on usage.

Although, my two cents would be to do both (you already typed them both out anyway!). I would put the functionality in the Arm class that way the Arm class can be used independently from the Person class. Then of course it doesn't hurt to create wrappers in the Person class for its members' functionally - especially if you want to keep the members hidden and only allow the Person class to be worked with directly. Again, it is dependent on usage.

Just a suggestion. Good luck.

Comments

0

Your problem is famously addressed my The Law of Demeter (LoD). This is the Wikipedia definition of the LoD:

Each unit should have only limited knowledge about other units: only units "closely" related to the current unit. Each unit should only talk to its friends; don't talk to strangers. Only talk to your immediate friends.

And these are the advantages of following the LoD:

The advantage of following the Law of Demeter is that the resulting software tends to be more maintainable and adaptable. Since objects are less dependent on the internal structure of other objects, object containers can be changed without reworking their callers.

There are also drawbacks that in particular cases might be sufficient to disregard the LoD:

Although the LoD increases the adaptiveness of a software system, it may also result in having to write many wrapper methods to propagate calls to components; in some cases, this can add noticeable time and space overhead.

However, to my knowledge adhering to the LoD is commonly regarded as good practice! So, to cut a long story short, go for your Scenario 1!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.