Regex Rookie
Regex Rookie

Reputation: 10662

Access private data member from a subclass

I would like to declare a data member of a superclass, private:

public abstract class superclass {
  private int verySensitive;

  abstract int setVerySensitive(int val); // must be overriden by subclass to work properly
}


public class subclass extends superclass {

  @Override
  protected int setVerySensitive(int val) {
    if (val > threshLow && val < threshHigh) // threshHigh is calculated in superclass constructor
       verySensitive = val;
  }
}

As you can see, I have a problem here: superclass can't access verySensitive because it's private, but I don't want to make verySensitive protected because it's... sensitive.

Also note that setVerySensitive was made abstract because checking against valid values can only be done after superclass has been constructed.

Can you recommend an elegant way of getting out of this "catch 22" situation?

Upvotes: 1

Views: 5009

Answers (8)

Leo Izen
Leo Izen

Reputation: 4289

Use reflect:

// SubClass.java
import java.lang.reflect.*;

class SuperClass {
    private String privateField = "This is Private";
    public SuperClass(){
    }
}
class SubClass extends SuperClass {
    void getPrivateField(){
        Field f = null;
        try {
            f = SuperClass.class.getDeclaredField("privateField");
        } catch (NoSuchFieldException nsfe){
            throw new Error();
        }
        f.setAccessible(true);
        try {
            System.out.println(f.get(this));
        } catch (IllegalAccessException iae){
            throw new Error();
        }
    }
    public static void main(String[] args){
        new SubClass().getPrivateField();
    }
}

Upvotes: 3

dnault
dnault

Reputation: 8899

Just how "sensitive" is this value? You may want to look into configuring a SecurityManager to prevent accessing the private field via reflection.

http://aminurrashid.com/english/java/core-java/prevent-reflection-to-access-private-methods-and-members-in-java-classes.html

Upvotes: 1

Ted Hopp
Ted Hopp

Reputation: 234795

I suggest something like this:

public abstract class superclass {
  private int verySensitive;

  final int setVerySensitive(int val) {
    if (checkVerySensitive(val)) {
      verySensitive = val;
    }
  }
  protected abstract boolean checkVerySensitive(int val);
}


public class subclass extends superclass {

  @Override
  protected boolean checkVerySensitive(int val) {
    return val > threshLow && val < threshHigh; // threshHigh is calculated in superclass constructor
  }
}

This is similar to EboMike's suggestion, but it leaves setVerySensitive(int) with package access instead of making it private.

Upvotes: 5

Jim Garrison
Jim Garrison

Reputation: 86774

Add

protected void setVerySensitive(int val) { verySensitive = val; }

in the superclass, then use that in the subclass to set the value.

Upvotes: 0

me_is_it
me_is_it

Reputation: 31

sorry, no way out.

Either it is private and only you can access it, or it is protected and it is part of your subclass signature.

Upvotes: 1

Stephan
Stephan

Reputation: 43023

Provide a protected method the child class can access for actually change verySensitive value.

Upvotes: 0

tvkanters
tvkanters

Reputation: 3523

I think the only answer that fits your criteria would be this:

public abstract class superclass {
  private int verySensitive;

  abstract int setVerySensitive(int val); // must be overriden by subclass to work properly

  protected void setVerySensitiveForReal(int val) {
    verySensitive = val;
  }
}


public class subclass extends superclass {

  @Override
  protected int setVerySensitive(int val) {
    if (val > threshLow && val < threshHigh) // threshHigh is calculated in superclass constructor
       setVerySensitiveForReal(val);
  }
}

It's not much different than simply making verySensitive protected but you have to be able to access it somewhere.

Upvotes: 1

EboMike
EboMike

Reputation: 77752

How about making the checking abstract, but the setting itself private?

public abstract class superclass {
  private int verySensitive;

  abstract boolean verifySensitiveValue(int val); // must be overriden by subclass to work properly

  private void setVerySensitiveValue(int val) {
    if (verifySensitiveValue(val)) {
      verySensitive = val;
    }
  }
}


public class subclass extends superclass {

  @Override
  protected boolean verifySensitiveValue(int val) {
    return (val > threshLow && val < threshHigh); // threshHigh is calculated in superclass constructor
  }
}

Upvotes: 6

Related Questions