Hi, when I started to look into programming, one of the things I remember many programmers are quite keen on are setters and getters. I totally understand the importance of them but there is one thing that isn't really clear to me. If I have a class with some private members declared in it and setters and getters like:

public class MyTest{
    private int variable1;
    private int variable2;
    ...
    //setter1
    public void setVar1( int theFirst){
        variable1 = theFirst;        
    }
    //setter2
    public void setVar2( int theSecond){        
        variable2 = theSecond;
    }
    //getter1
    public int getVar1(){
        return variable1;
    }
    //getter2
    public int getVar2(){
        return variable2;
    }

    public void doSomething( int theFirst, int theSecond){
        ...
    }
}

and a test class like
public class TheTest{
    int firstVar = 34;
    int secondVar = 20;

    MyTest probe = new MyTest();

    setVar1(firstVar);
    setVar2(secondVar);

    doSomething( firstVar, secondVar);

}

Now my question is this: in the above code I call the setter once to set the value of
the instance variables. I need to use these variables (variable1 and variable2) in my doSomething function but
I am thinking, because I have the setters, this type of call doSomething( firstVar, secondVar); - in which I
pass the local variables to the function - is needless: I might as well do instead doSomething(); , passing no parameters at all and then inside doSomething edit directly variable1 and variable2.
So what's the best way? using setters or passing variables to the function?
thanks

Dani AI

Generated

Short answer: prefer passing transient user input (like a chosen row/column) as parameters; keep the board and any long‑lived game state as fields. That follows ’s distinction about hidden dependencies and complements ’s point that setters are useful when they can enforce validation. The TicTacToe sketch from highlights the common confusion: a "selected square" is usually a transient input, not an intrinsic attribute of the board object.

Practical rules of thumb:

  • Keep I/O separate from the model. Read and sanitize user input in the UI/main loop, then pass validated values into the board API.
  • Use fields for true object state (the board array, current player, move history). Use parameters for per-call data that can vary repeatedly between calls.
  • Avoid setters that merely mirror fields unless they enforce invariants. Validation is useful, but validate at the boundary and inside model methods as needed.
  • Make method results explicit rather than implicit: return structured status or enums instead of a boolean whose meaning can be misread.

Example API pattern (illustrative only):

public enum MoveResult { OK, OUT_OF_RANGE, OCCUPIED, WIN, DRAW }

public MoveResult placeMark(int row, int col) { ... }

public boolean isEmpty(int row, int col) { ... }

Quick troubleshooting checklist:

  • Use clear names (isEmpty vs isOccupied) so return semantics are obvious; the existing checkSquare semantics are easy to misinterpret.
  • Watch off‑by‑one (user numbering vs 0‑based arrays) and always validate range before indexing.
  • Unit test board logic independently of input handling.
  • If the board may be used from multiple threads (GUI or network clients later), design for thread safety rather than relying on externally set fields.

These practices keep the API clear, easier to test, and less error prone.

Recommended Answers

All 9 Replies

There's no one right answer to this, but here are two very short answers to start the discussion...

If those values represent something persistent about the MyTest instance that is relevant to a number of methods then they should be instance vars (with getters/setters) and should not be passed in as parameters.

If they are just needed for the doSomething method, and will vary from one call to the next, then they should be passed in as parameters, and there's no reason for them to be instance variables.

setters and getters can also help you improve encapsulation in your classes.
let's say you have a class 'Person', with age as variable (an int). if it's not set as private, you can put any value there. ever seen a Person that's negative 200 years old?
but, with setters, you can add some validation:

public void setAge(int age){
      if ( age < 0 || age > 120 ) throw new Exception("Invalid age");
      this.age = age;
}

Thanks for that. The code posted is obviously a small example and part of a bigger program.

If those values represent something persistent about the MyTest instance that is relevant to a number of methods

That is correct they will be used in a number of methods and (I haven't included this in the example for brevity) their value comes from a user input, so the idea is that users type in the value and then I do whatever check is needed, which actually involves several methods testing those values. The values of the variables stay the same for quite awhile, surely till after all the checks have been made and then (everything will be in a loop) users are asked to input another 2 values for the same variables and it all starts again till the condition used in the loop become false or something like that.
So based on what you said, I think that it will be best to use setter and getters rather than passing parameters. Somehow it felt more right to pass the values as parameters, I don't know why just a feeling, but I will go with the suggestion

From your description it's not clear which is better. It sounds like the clearest structure could be

while (more)
   get user input
   if (isValid(input)) process(input)

isValid may involve a number of separate methods, but personally I would hide that complexity inside a single "master" method, rather than clutter the main loop with irrelevant detail.

My objection to using instance variables here is that they are a form of hidden dependency between method calls - the methods need the variables to have been set, and may assume that they have already been processed by another method, but that's not obvious.

it is something similar to that. ok here's the code (I didn't post it before because i thought we could do with just a sample).
this is the file with methods and classes:

/*TicTacToe.java*/
public class TicTacToe{     
    private TicTacToeEn[][] board = new TicTacToeEn[3][3];//to represent the 3-by-3 board
    private int row;//row of the 3-by-3 board
    private int column;//column of the 3-by-3 board         

    public enum TicTacToeEn{
        X, O, EMPTY 
    }//end of enum
    TicTacToeEn theSymbol;//of type enum holds the current theSymbol, X or O 
    //constructor
    public TicTacToe(){
        for( int i = 0; i < board.length; i++ ){
            for( int j = 0; j < board[i].length; j++ ){
                board[i][j] = TicTacToeEn.EMPTY;
            }//columns
        }//rows         
    }//end of constructor

    //row setter    
    public void setRow( int theRow ){
        row = theRow;       
    }
    //column setter
    public void setColumn( int theColumn ){
        column = theColumn;
    }

    //checks if square is empty
    public boolean checkSquare(int number1, int number2){
        if(board[number1][number2] == TicTacToeEn.EMPTY){
            return false;
        }
        else{
            return true;
        }       
    }//end of checkSquare()
    ...

here's the test file (but I haven't developed the whole thing as yet, still working on it, and there will be calls to methods etc)

/*TicTacToeTest.java*/
import java.util.Scanner;

public class TicTacToeTest{
    boolean isFull = false;//if true all the squares have been assigned.
    boolean isDraw = false;//to check if the game is draw
    boolean squareStatus = false;//returns the status of a square, if false the square is full if true the square is empty
    boolean victory = false;//if returns true one of the players has won
    int rowInput;
    int colInput;

    public static void main( String args[] ){
        Scanner input = new Scanner( System.in );
         TicTacToe probe = new TicTacToe();
        while(!isFull){
        ...
        //get the values of rowInput and colInput from user

        probe.checkSquare( rowInput, colInput);
        ...
        }

    }//end main

}//end TicTacToeTest class

So in here as you can see I have some local variables int rowInput; and int colInput; whose values will be determined by the user. That done, I have 2 options: either use setters and assign their values to the instance variables row and colum or pass them as parameters to the methods everytime I need the methods to do some checks (here I have only one method checkSquare
but there will be a few more, most of them in need to access the row and the column value)

This can work either way, so it's a question of which is clearer/safer. Here's my opinion...
the user's selected row/col is a transient kind of thing that isn't really an attribute of the ttt board, so I would go with local variables in the user input method, and pass them to validation methods etc as required.

ok sounds good to me.
I must admit I was a bit confused, because at the beginning I did include the row and column as attributes of the board, because at the end of the day they somehow 'describe' a single cell giving its position. But on the other hand, it felt euqlly good to have them as instance variables...I really had no idea what to do. But also as stultuske pointed out, using getters and setters promote encapsulation and I remember this is also another key thing that many programmers, quite rightly I think, are very keen on. So in essence I really didn't know what to do!

It's true that getters and setters promote encapsulation compared to directly sharing variables. But passing values as parameters keeps them in a smaller scope which is even more "encapsulated".

ok, then local variables will be!
thanks

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.