[英]Java Inheritance - setters only in subtypes
我们有两个班级(一个父母和一个孩子)。 两者都使用私有变量来存储值,但父级不应该提供设置器(x和y是由构造函数提供的,它们是某种不可变的)。 B应该用x和y的二传手扩展A。 有一种通用的方法吗?
class A{
private int x;
private int y;
A(int x, int y){
this.x = x;
this.y = y;
}
}
class B extends A{
public void setx(int x){
this.x = x;
}
//same for y
}
一些想法
在基类中声明protected
的变量,并在子类中编写getter和setter。
如果您希望变量不可变,则应为
class B extends A{
public B(int x, int y){
super(x, y);
}
}
目前,您在A中的x和y变量是不可变的。 为了使它们不可变,然后在它们之前添加final
这是分配x和y私有的唯一方法。 如果要使用setter,则必须使变量受保护。
我个人是不变性的忠实拥护者,因此可以做到这一点,而不是二传手-创建对象通常非常便宜。
您不能有一个私有成员变量,也没有方法(这里的方法也指构造函数)来设置它(从技术上讲可以,但是没有意义)。 如果要从派生类设置变量,则必须对其进行保护。
编辑:但是,您可以在基类中定义一个受保护的“帮助程序”设置程序,并从派生类中的公共设置程序调用此受保护的帮助程序设置程序。
第二次编辑:另一种可能性是在基类中定义一个抽象的getter,并在派生类(模板模式)中实现getter,setter和private字段。
这是一个很奇怪的问题,它是一成不变但可变的,是私人的却是公共的……正确的方法应该是使它们受到保护,正如每个人都说的那样。
无论如何,在Java中,如果安全管理器没有抱怨,您可以使用肮脏的技巧,请检查以下内容:
import java.lang.reflect.Field;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Priv
{
public static class A
{
private final int x;
public A(int x)
{
this.x = x;
}
}
public static class B extends A
{
public B(int x)
{
super(x);
}
public void setX(int x)
{
Class c = A.class;
try
{
Field f = c.getDeclaredField("x");
f.setAccessible(true);
f.set(this, x);
} catch (IllegalArgumentException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchFieldException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
}
}
public int getX()
{
int v = 0;
try {
Class c = A.class;
Field f = c.getDeclaredField("x");
f.setAccessible(true);
v = f.getInt(this);
} catch (IllegalArgumentException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchFieldException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
}
return v;
}
}
public static void main(String[] args)
{
B b = new B(5);
System.out.println("b.x is " + b.getX());
b.setX(42);
System.out.println("b.x now is " + b.getX());
}
}
没有不变的概念,您有任何调用super的setter方法或子类的构造函数来重新初始化私有的super类的变量。
不可变本质上是线程安全的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.