Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why getter & setter if return value is mutable?

In C++ a getter & setter for a private data member is very useful due to the ability to control mutability via a const return value.

In Java, if I understand correctly (please correct me if I am mistaken), specifying final on a getter doesn't work that way. Once the caller received the data member reference through the getter, it can modify it, despite it being private...

If that's the case (and please correct me if I have a gross misconception here), why not declare the data member public and simplify things?

like image 604
ateiob Avatar asked Sep 12 '11 13:09

ateiob


People also ask

Why do we need a getter and setter?

Getters and setters are used to protect your data, particularly when creating classes. For each instance variable, a getter method returns its value while a setter method sets or updates its value. Given this, getters and setters are also known as accessors and mutators, respectively.

What is the advantage of using getters and setters that only get and set instead of simply using public fields for those variables?

1) getter and setter method gives you centralized control on how a the particular field is initialized and provided to the client which makes the validation and debugging much easier. you can simply put breakpoints or print statement to see which thread are accessing and what values are going out.

What is a getter method?

Getter and Setter are methods used to protect your data and make your code more secure. Getter returns the value (accessors), it returns the value of data type int, String, double, float, etc. For the program's convenience, getter starts with the word “get” followed by the variable name.

Why do we need getters and setters C++?

The getter function is used to retrieve the variable value and the setter function is used to set the variable value. Remember: You can directly access public member variables, but private member variables are not accessible. Therefore, we need getter functions.


2 Answers

If you want your class to be immutable (i.e. having only final fields and getters) you must be sure that the values you return are immutable as well. You get this for free when returning Strings and built-in primitives, however some extra steps are necessary for other data types:

  • wrap collections with immutable decorators or defensively copy them before returning from a getter
  • make a copy of Date and Calendar
  • Only return immutable objects or defensively clone them. This also applies to objects in collections.

Note that if you defensively copy a collection, the client can view or modify the copy, but this does not affect the original collection:

return new ArrayList<Foo>(foos);

On the other hand if you wrap the original collection, the client is able to see all the changes that were introduced to the collection after the wrapper was created, but trying to change the contents of the wrapper will result in runtime exception:

return Collections.unmodifiableList(foos);

The bottom line is: Foo has to be immutable as well, otherwise the collection is immutable, but the client code can still modify members of the collection. So the same rules apply to Foo.

If that's the case (and please correct me if I have a gross misconception here), why not declare the data member public and simplify things?

Because:

  • you might wish to store mutable data inside an object and only provide immutable (read-only) view of the data (like wrapping collections)
  • you can change the implementation in the future, get rid of the field and for instance compute the value on the fly.
like image 45
Tomasz Nurkiewicz Avatar answered Nov 16 '22 02:11

Tomasz Nurkiewicz


Making immutable return values in java is a matter of either returning already immutable objects types (such as String) or returning a copy for non-immutable objects.


Sample 1 - Already immutable object

public String getValue() {
    return value;
}

Sample 2 - Collection of already immutable objects

public List<String> getValues() {
    return new ArrayList<String>(values);
}

Sample 3 - Non-immutable object

public Complex getComplex() {
    return complex.clone();
}

Sample 4 - Collection of non-immutable objects

public List<Complex> getComplex() {
    List<Complex> copy = new ArrayList<Complex>(complexs.size());
    for (Complex c : complexs) 
        copy.add(c.clone());
    return copy;
}

Sample 3 and 4 are for conveniance based on that the complex type implements the Cloneable interface.

Furthermore, to avoid subclasses overriding your immutable methods you can declare them final. As a side note, the builder pattern is typically useful for constructing immutable objects.

like image 109
Johan Sjöberg Avatar answered Nov 16 '22 03:11

Johan Sjöberg