taylordurden
taylordurden

Reputation: 357

Correct way to expose instance variables to other classes

Can someone help me understand this:

"For example, an object's instance variables (member fields that aren't constants), should always be private. Period. No exceptions. Ever. I mean it. (You can occasionally use protected methods effectively, but protected instance variables are an abomination.) You should never use get/set functions for the same reason—they're just overly complicated ways to make a field public (though access functions that return full-blown objects rather than a basic-type value are reasonable in situations where the returned object's class is a key abstraction in the design)." - http://www.javaworld.com/article/2073649/core-java/why-extends-is-evil.html

I don't understand what he means by, "You should never use get/set functions for the same reason—they're just overly complicated ways to make a field public." Let's say I have a simple Person class with Name and Age instance variables. How should I make these available to other classes? Does he mean that I should create a Data Transfer Object? Would this be a correct implementation? Is this really preferable to having the getters and setters in the Person class?

public class Person {
    private PersonData personData;

    public Person (String name, int age){
        this.personData = 
            new PersonData(name, age);
    }

    // get personData

    // person methods...
}

// data transfer object
class PersonData {
    private String name;
    private int age;
    public PersonData(String name, int age){
        this.setName(name);
        this.setAge(age);
    }
    // getters and setters ...
}

Upvotes: 2

Views: 2533

Answers (4)

Himanshu Lakhara
Himanshu Lakhara

Reputation: 80

Correct way to expose instance variables to other classes

You should provide as low access to instance field as possible. The preferred way to provide access is to have three items

  1. A private field
  2. An public accessor method
  3. An public mutator method

This Approach has following benefits

First benefit: This approach increases abstraction.

Suppose the getter(or accessor) method for Name is defined as follows

String getName() {
    return name;
}

Now for some reason you want to change implementation of name as

String firstName;
String lastName;

In this case you can change getName() as

String getName() {
    return firstName + " " + lastName;
}

Using this approach does not break your existing code which otherwise would be difficult(if not impossible) to obtain.

Second benefit: You can perform error checking all at once.

Consider a situation when the age entered by user is negative or practically impossible (like 99999999). In that case you can check such input in mutator method. This avoid manual checking and repetition of error check at different places

In addition it is advised that you should not write accessor method that return references to mutable object. This will break encapsulation. Use .clone() method of object class to return an object.

Upvotes: 0

SJuan76
SJuan76

Reputation: 24895

More of a comment that an answer...

The article is dedicated to stablishing the need/advantages of loose coupling, and techniques to get it.

One of the points is avoiding relying in the internal data structure of an object, and only use its operators. In that point, automatically making your state accessible is bad, since objects using your classes may rely in these properties instead of using the more "refined" operations given to them.

From my understanding of the article, a possible example could be the following:

Imagine a Person class/interface with two operations, say, isOldEnoughToBuyBeer and isOldEnoughToDriveCars.

if you create in Person a setter/getter for dateOfBirth, then you are tying the implementations of Person to have such a property, and to implement the operations as "check current date agains dateOfBirth property and return true based in the number of years".

Of course, the statement "You should never use get/set functions for the same reason—they're just overly complicated ways to make a field public" may be too restrictive; while it is making a good point that even access through getters/setters has its consequences, it is hard to imagine that attributes are used only internally to the class that holds them.

Upvotes: 1

acdcjunior
acdcjunior

Reputation: 135862

The author argues that you should never have public instance variables. (Because they break encapsulation, but I believe you are not quiestioning this - if needed, though, we can get to it.)

When he says "You should never use get/set functions for the same reason" he's saying that, in practice, having public get and set methods for an instance variable is roughly* the same as having the varible itself public.

The only difference (and the reason why he writes "they're just overly complicated ways to make a field public"), is that instead of the modifier public in the instance variable, you created two additional methods.

(Data) Transfer Objects are a complete different animal, they aren't related to the discussed context.


* "Roughly" because we are talking about the (usual) hipothesis of the getter and setter just reading and writing to the instance variable, not doing any additional processing.

Upvotes: 0

Eran
Eran

Reputation: 394136

You should definitely have getters for all the properties of the object you wish to expose to other objects. And if your object is mutable, you'll probably want setter methods for all the properties that can be modified.

set/get methods are not overly complicated ways to make a field public. They allow you to control the access and modification of your members.

For example, if your class is immutable, a get method that returns some object would return a clone of that object, to prevent the caller from modifing it.

For another example, if your class is mutable, a setter can contain validation of the new value you are trying to set.

Upvotes: 1

Related Questions