Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java- Best practice for getters, single getter or multiple for different variables?

I am relatively new to Android programming (~ 2 Months) Is it necessary to have getters for dozens of different variables?

For example -

//Yes I realise that this isn't 'dozens'
public float getX() {
    return position.x;
}

public float getY() {
    return position.y;
}

public float getWidth() {
    return width;
}

public float getHeight() {
    return height;
}

public float getRotation() {
    return rotation;
}

While it would be necessary to have different getters and setters for floats and strings for example, is it bad practise, and if so why is it, to use something like a switch statement to return different variables?

public float returnSomething(String theThing) {
    switch (theThing) {
        case "height":
            return height;
        case "rotation" :
            return  rotation;
        case "width":
            return  width;

        default:
            return 0;
    }
}

So, is the above code considered bad? If so, please explain why.

Thanks for any help, this isn't really a problem as either way works fine, I just don't see why people would use dozens of getters and setters if there isn't a good reason.

I suppose the same question applies to setters

like image 954
Theo Pearson-Bray Avatar asked Jul 20 '15 13:07

Theo Pearson-Bray


2 Answers

Because the moment you do something like

public float returnSomething(String theThing) {
    switch (theThing) {
        case "height":
            return height;
        case "rotation" :
            return  rotation;
        case "width":
            return  width;

        default:
            return 0;
    }
}

I can feel the next question for Stack Overflow, "Why is my height always 0?"

And then post code like

public class GameThingy {
      //...

     private void doStuff(GameObject gameObject) {
         float gravity = 5*gameObject.returnSomething("hieght");
         gameObject.setSomething("velocyty", gravity+50);
     }
}

Technically the moment you make a typo anywhere, you'll have issues finding the source of the problem. That, and you're lucky that the fields are all float, they don't have to be.

Edit: By the way, this is actually a typical problem in defining the field of interest in some database queries. As in, having to specify the field you're looking for by a String.

A real-life example is RealmQuery<T>.

A RealmQuery<T> looks like this:

RealmQuery<User> query = realm.where(User.class);

// Add query conditions:
query.equalTo("name", "John");

// Execute the query:
RealmResults<User> result1 = query.findAll();

Where they assume the class User is something like this:

public class User {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

An interesting note is that Realm creates a "proxy subclass" where they redefine the setName and getName methods (aka, you need getters/setters to make some systems work! They assume you have them!)

But what's important here is that you need to provide the field name with "name".

Later on, anyone can make a typo, or you just won't remember the fields off the top of your head. In this particular case, they tend to create a metamodel (something that stores the name of the fields for you) for the purpose that you won't have to use Strings to refer to field names.

For example, in Criteria API, instead of

Root<Pet> pet = cq.from(Pet.class);
cq.select(pet.get("name"));

They have the metamodel like this:

Root<Pet> pet = cq.from(Pet.class);
cq.select(pet.get(Pet_.name));

Thus, it eliminates the need for Strings.

And similarly, what I tend to do with Realm is that I create a "metamodel" (although you can now have it generated for you automatically with RealmFieldNamesHelper):

public class User
        extends RealmObject {
    @PrimaryKey
    private long id;
    private String name;

    public static enum Fields { //this is the "metamodel"
        ID("id"),
        NAME("name");

        private String fieldName;

        Fields(String fieldName) {
            this.fieldName = fieldName;
        }

        public String getField() {
            return fieldName;
        }

        @Override
        public String toString() {
            return getField();
        }
    }
}

And thus you can replace the query like so

RealmResults<User> result2 = realm.where(User.class)
                                  .equalTo(User.Fields.NAME.getField(), "John")
                                  .or()
                                  .equalTo(User.Fields.NAME.getField(), "Peter")
                                  .findAll();

But with getters and setters, you already have the type safety, and you already have the methods that you don't have to remember off the top of your head - and so, you have the compilation time error checks.

So to answer your question, the reason why it's a bad practice to refer to variables by string name in Java is because

1.) typos can happen, and the error occurs only in runtime, not compile time

2.) it is not type-safe; you are lucky that you get floats back no matter what in this example, but the moment it can be a String, you need to return Object and cast it or use public <T> T get(String field) { ... } and whoever calls the method must know exactly what they are receiving - also runtime-error prone.

like image 122
EpicPandaForce Avatar answered Sep 28 '22 04:09

EpicPandaForce


Getters & Setters give you type safety. However use it only for variables that you need to access (get/set) from outside the class. You can and should minimize it by using suitable constructors, which for most cases is the right way to go because it increases clarity of the code by eliminating magical changes in the background, which can be a serious pain for multi-threaded code but can be a big issues even in regular code with poor programming.

Just because you have twenty class level private variables doesn't mean you have to create getXXX() & setXXX() for each!

BTW: Most IDE's these days like Eclipse can automatically generate them for you.

like image 42
Angsuman Chakraborty Avatar answered Sep 28 '22 05:09

Angsuman Chakraborty