Java继承 - 仅在子类型中设置

时间:2012-11-13 10:39:39

标签: java inheritance subtype

我们有两个类(一个父类和一个子类)。两者都使用私有变量来存储值,但父级不应该提供setter(x和y是用构造函数给出的,它们是某种不可变的)。 B应该用x和y的setter扩展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必须提供公共设定者

5 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:3)

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

class B extends A{

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

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

之前

这是你可以分配x和y的唯一方法,因为它们是私有的。如果你想要setter那么你必须保护变量。

就个人而言,我是不变的忠实粉丝,所以这样做而不是制定者 - 创造物品通常很便宜。

答案 2 :(得分:1)

你不能拥有一个私有成员变量,也没有方法(这里有方法,我的意思也就是构造函数)设置它(好吧,技术上你可以,但它没有意义)。如果希望变量可以从派生类中设置,则必须对它们进行保护。

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

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

答案 3 :(得分: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());
    }

}

答案 4 :(得分:0)

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

immutable本质上是线程安全的。