Skip to main content

(Not So) Stupid Questions 3: Private Access

December 17, 2004


(Not So) Stupid Questions

Private Access





Editor's note: Sometimes, the most interesting discussions begin when someone says, "This may be a stupid question, but ..." If the person asking the question has taken the time to think about the problem before asking, the question is often not stupid at all. Uncertainty points out an ambiguity in the specs, holes in the docs, or a search for how more experienced programmers might address a particular problem. From time to time, we will publish one of the "(Not So) Stupid Questions" we receive and invite our readers to answer the question in the feedback section. This one began in a different form as a suggestion from Vladimir V. Ostromensky. He sent us some sample code, somewhat like the code we present below, with a question about String equality. We have adapted and extended his initial question.

Remember that new people are joining the Java community all the time and may be looking for help from those with more experience. Also, those who began with Java as their first language can benefit from those coming to the community with experience in other languages. As always, answer the questions with kindness. You are also welcome to submit your questions to .

This may be a stupid question, but ... "Some uses of the private keyword don't make sense."

First thoughts:

To encapsulate a class, we are told to make all instance variables private. Even setters can violate encapsulation, so consider this example of an encapsulated class.

class Fraction {

  private int numerator;
  private int denominator;
 
  public Fraction(int numerator, int denominator) {
    this.numerator = numerator;
    this.denominator = denominator;
  }
 
  public int getNumerator(){
    return numerator;
  }
 
  public int getDenominator(){
    return denominator;
  }
 
  public Fraction multiply( Fraction x ){
    return new Fraction ( numerator * x.numerator,
                          denominator * x.denominator);
  }
 
  public Fraction divide( Fraction x) {
    return new Fraction ( numerator * x.denominator,
                          denominator * x.numerator);
  }
 
}

The public interface is a constructor and methods to multiply and divide Fractions. We can exercise the code like this:

class Exercisor {

  public static void main( String[] args) {
    Fraction f = new Fraction( 1, 3 );
    Fraction g = new Fraction( 2, 5 );
    Fraction quotient = f.divide(g);
    Fraction product = f.multiply(g);
   
    System.out.println("1/3 * 2/5 = " +
      product.getNumerator() + "/" +
      product.getDenominator());
     
    System.out.println("1/3 / 2/5 = " +
      quotient.getNumerator() + "/" +
      quotient.getDenominator());
  }
}

In J2SE 5.0, you can easily change the type of numerator and denominator from ints to Integers and the code will still compile and run. This is the mark of a well encapsulated class - isn't it? Note that we need to use getNumerator() and getDenominator() from Exercisor, but that we can directly access the numerator and denominator from within Fraction.

In other words: objects can see the private variables and methods of an object of the same type. The private keyword is class-private, not object-private.

Note that to divide fractions, we invert the second fraction and multiply. If we change the implementation of Fraction, we can introduce a side effect that can introduce mistakes for client classes.

class Fraction {

  private int numerator;
  private int denominator;
 
  Fraction(int numerator, int denominator) {
    this.numerator = numerator;
    this.denominator = denominator;
  }
 
  public int getNumerator(){
    return numerator;
  }
 
  public int getDenominator(){
    return denominator;
  }
 
  public Fraction multiply( Fraction x ){
    return new Fraction ( numerator * x.numerator,
                          denominator * x.denominator);
  }
 
  public Fraction divide( Fraction x) {
    int temp = x.numerator;
    x.numerator = x.denominator;
    x.denominator = temp;
    return multiply(x);
  }

 
 
}

Now Exercisor returns 5/6 for both the product and the quotient, because the divide() method is permitted to swap the argument's numerator and denominator fields, even though these have private access. The result is that the second fraction is replaced with its reciprocal.

This brings me to three questions:

1. When do I want to use private?

2. What are the recommendations for using the other keywords? and

3. Is there be a way of enforcing object privacy? Should I even be worrying about this?

(Not So) Stupid Questions is where we feature the questions you want to ask, but aren't sure how.

Related Topics >> Programming   |