Getter for a private member object in Java

Let's say that I have a class called Truck , and one of the private member variables has the Wheel class. The getter for the Wheel variable, getWheel , will return a reference to it as follows:

 class Truck{ private Wheel wheel; Truck(){ wheel=new Wheel(); } Wheel getWheel(){ return this.wheel; } } class Wheel{ int color; } 

Now, anyone who calls getWheel can optionally modify the private member:

 class me{ public static void main(String[] args){ Truck ye=new Truck(); Wheel v=ye.getWheel(); v.color=2; } } 

It will defeat encapsulation, right?

What would be the appropriate remedy for this?

+5
source share
2 answers

Common approaches are:

  • Make a protective copy (e.g. return a copy of Wheel )
  • Make Wheel immutable (anytime you want to change it, instead you create a new one, created with a new color)
  • Do not return the Wheel , return an immutable interface on the Wheel , which returns only getters, mutation operations
  • As Sandeep said , make the setter more limited than the receiver, say package-private for the setter and public for the receiver. Then the classes inside the package can set the Wheel color, but the classes outside the package cannot. (I prefer # 3 in this situation for a clear separation, but this also works if you cross the line of sight.)

This third option is one of the reasons why instance variables (fields) not private are often considered bad practice.

Here is # 3 in more detail, simply because it is more complex than # 1 and # 2, and not because it is necessarily better (itโ€™s not so, the choice of design is made in context).

A read-only interface, usually open or batch-private, depending on how you intend to use all of this:

 public interface Wheel { int getColor(); } 

A specific class, usually private-private (may be a private static nested class inside Truck , if this is the only place he used):

 class WheelImplementation implements Wheel { private int color; WheelImplementation(int color) { this.color = color; } public int getColor() { return this.color; } void setColor(int color) { this.color = color; } } 

Truck , usually the same visibility as Wheel :

 public class Truck { private WheelImplementation wheel; Truck(){ this.wheel = new WheelImplementation(/*...initial color...*/); } Wheel getWheel() { return this.wheel; } } 

Of course, this can be played through reflection, but in general, you are developing an API for use, not abuse. :-)

+8
source

You can create your own / batch setter for the color of the wheels. Also, initialize the color in the constructor, which will help you with this.

And like other answers, returning a copy of the Wheel is also a good way to do this.

+2
source

Source: https://habr.com/ru/post/1266155/


All Articles