从子类访问私有数据成员

时间:2011-03-31 19:37:07

标签: java oop visibility encapsulation

我想声明一个超类私有的数据成员:

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;
  }
}

正如你所看到的,我在这里有一个问题:超类不能访问verySensitive,因为它是私有的,但我不想让verySensitive受到保护,因为它是......敏感的。

另请注意,setVerySensitive是抽象的,因为只有在构造了超类之后才能检查有效值。

你能推荐一种优雅的方式摆脱这种“捕获22”的情况吗?

8 个答案:

答案 0 :(得分:6)

如何使检查抽象,但设置本身是私有的?

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
  }
}

答案 1 :(得分:5)

我建议这样的事情:

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
  }
}

这类似于EboMike的建议,但它使setVerySensitive(int)具有包访问权限,而不是将其设为私有。

答案 2 :(得分:3)

使用反射:

// 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();
    }
}

答案 3 :(得分:1)

我认为唯一符合您标准的答案是:

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);
  }
}

与简单地verySensitive受保护但没有太大区别,但您必须能够在某处访问它。

答案 4 :(得分:1)

抱歉,没有出路。

它是私有的,只有你可以访问它,或者它受到保护,它是你的子类签名的一部分。

答案 5 :(得分:1)

这个值有多“敏感”?您可能希望查看配置SecurityManager以防止通过反射访问私有字段。

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

答案 6 :(得分:0)

提供子类可以访问的受保护方法,以实际更改verySensitive值。

答案 7 :(得分:0)

添加

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

在超类中,然后在子类中使用它来设置值。