1

我们有两个班级(一个父母和一个孩子)。两者都使用私有变量来存储值,但父级不应提供设置器(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
}

一些想法

  • 变量应该是私有的
  • 父级的 x 和 y 必须是不可变的
  • B 必须提供一个公共设置器
4

5 回答 5

3

在基类中声明变量,protected并在子类中编写 getter 和 setter。

于 2012-11-13T10:43:56.477 回答
3

如果您希望变量是不可变的,那么它应该是

class B extends A{

    public B(int x, int y){
          super(x, y);
    }
}

目前,您在 A 中的 x 和 y 变量不是不可变的。为了使它们不可变,然后在它们前面加上final

这是您可以分配 x 和 y 的唯一方法,因为它们是私有的。如果你想要设置器,那么你将不得不保护变量。

就我个人而言,我是不变性的忠实拥护者,所以会这样做而不是 setter - 创建对象通常很便宜。

于 2012-11-13T10:44:38.753 回答
1

你不能有一个私有成员变量并且没有设置它的方法(这里的方法我也指构造函数)(嗯,从技术上讲你可以,但它没有意义)。如果您希望您的变量可以从派生类中设置,它们必须受到保护。

编辑:但是,您可以在基类中定义受保护的“帮助器”设置器,并从派生类中的公共设置器中调用此受保护的帮助器设置器。

第二次编辑:另一种可能性是在基类中定义一个抽象 getter,并在派生类中实现 getter、setter 以及私有字段(模板模式)。

于 2012-11-13T10:42:45.573 回答
0

没有不可变的概念是你有任何设置方法或子类的构造函数调用 super 来重新初始化超类的私有变量。

immutable本质上是线程安全的。

于 2012-11-13T13:29:22.880 回答
0

这是一个奇怪的问题,不可变但可变,私有但公开......正确的方法应该是让它们受到保护,正如大家所说的那样。

无论如何,如果安全管理器没有抱怨,你可以在 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());
    }

}
于 2012-11-13T11:07:18.547 回答