【问题标题】:JAVA Inheriting static field from base class in the way that it will differ for every subclassJAVA从基类继承静态字段,每个子类都会有所不同
【发布时间】:2015-02-19 19:00:39
【问题描述】:

我有一个基类

public class base
{
    //some stuff
}

和几个子类

public class sub1 extends base
{
static int variable;
}
public class sub2 extends base
{
static int variable;
}

静态 int 变量存在于每个子类中,因为我在其中存储了每个子类的特征信息。但是,如果有一种方法可以将静态 int 变量移动到基类,并且每个子类仍然会有所不同,那就更好了。 就像我现在重复自己的方式一样,在添加另一个子类时,这是一种不好的做法。

所以有人知道如何完成这个吗?也许有适合这种情况的设计模式?

【问题讨论】:

  • 如果价值观不同,你是如何重复自己的?
  • 给定子类的值是随时间变化的,还是不变的?
  • @Bohemian 没有。
  • @BartlomiejLewandowski 当我创建 sub1 的 2 个对象时,我希望它们具有相同的变量值,但不同于 sub2 对象,例如:sub1 obj1 = new sub1();// value =x sub1 obj2 = new sub1();// value =x sub2 obj3 = new sub2();//value =y sub2 obj4 = new sub2();//value =y 现在假设我有 5 个使用静态变量的方法必须在每个子类中实现它们,但它们都是一样的——我在重复自己

标签: java inheritance static field


【解决方案1】:

您不能将所有不同的静态变量从派生类移到基类中,因为static 变量是每个类一个;你希望你的变量是每个子类一个,这是不允许的。

您可以通过在基类中定义子类注册表来解决此问题,并将每个子类的int 存储在那里。但是,这会增加很多复杂性,并且不清楚如何区分超类中的子类。

您当前的解决方案似乎是最佳的。

【讨论】:

    【解决方案2】:

    您当然可以将变量移动到基类中,但它不能是静态的。或者,您可以制作在每个子类中覆盖的静态 getter。以下是两者的示例:

    public class base {
        protected int variable;
        protected static int getVariable() {
           return -1;
        }
    }
    
    public class Sub1 extends base {
        public Base() {
            variable = 0;
        }
        protected static int getVariable() {
            return 0;
        }
    }
    public class Sub2 extends base {
        public Sub2() {
            variable = 1;
        }
        protected static int getVariable() {
            return 1;
        }
    }
    

    作为设计原则,您真正需要静态方法的情况很少(在我看来)。通常你会有一些你正在使用的类的实例。如果您希望一大堆对象共享您在运行时配置的一些常见行为,您可能需要查看享元模式。

    【讨论】:

    • Java 不允许覆盖静态方法。您的建议是简单的重新定义。在编译时根据引用变量的类型确定将调用哪些方法。例如:base b = new Sub2(); b.getVariable(); 将返回 -1
    • 无论变量包含什么,如果它返回一个常量,静态 getter 方法的意义何在?
    • 这不是关于从方法返回的内容,而是关于调用哪个静态方法。如果在您的代码中使用引用变量 (base b; b.getVariable()) 调用静态方法,则该引用变量的类型决定调用哪个方法。如果您在代码中使用类 (Sub2.getVariable()) 调用静态方法,则将调用该类中定义的方法。
    • 尝试运行代码。我向你保证,你可以实例化一个新的 Sub1(),而 getVariable() 将返回 1。不过你是对的,如果你将它设置为 Base,它将不再返回 1。
    • new Sub1().getVariable() 将返回1 - 因为new Sub1() 返回Sub1 类型的“不可见”引用变量。但是base b = new Sub1(); b.getVariable() 将返回-1 - 因为引用变量bbase 类型(尽管它引用的对象是Sub1 类型)
    【解决方案3】:

    不要为此使用静态字段 - 这不是要走的路,因为子类的静态字段不会“覆盖”超类的静态字段。

    相反,由于给定类的值是常量,请使用最终实例字段:

    public class Base {
        protected final int variable;
        public Base() {
            this(5);
        }
        protected Base(int v) {
            variable = v;
        }
    }
    
    public class Sub1 extends Base {
         private static int v = 7;
         public Sub1() {
            super(v);
        }
    }
    

    现在变量是固定的,所有实例都可以访问。

    【讨论】:

    • 是的,但问题是我发布的示例是简化的ofc,在实际代码中变量是对象(我的意思是某种大对象)并且会有大量的子类对象在应用程序运行期间创建,因此使其成为非静态(为同一子类的每个对象创建新变量)会影响性能。
    • @Rotek 查看对子类的更改以避免重新创造价值。此外,如果 Base 从未直接使用,请考虑将其设为 abstract 并删除默认构造函数
    猜你喜欢
    • 2012-03-30
    • 2011-04-02
    • 1970-01-01
    • 2018-10-04
    • 2012-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-05
    相关资源
    最近更新 更多