我的子类如何正确继承静态变量

3
public abstract class SuperClass {
    public int x, y;
    public static int z;
}

我希望每个SuperClass的子类都有静态变量z。当然,对于每个子类,z的值都将不同。我希望避免在每个子类中定义z,因为它将是值x和y的功能依赖关系。这种情况是否可行?


不,static变量属于声明它们的类。你能做的最好的事情就是隐藏它们。 - Sotirios Delimanolis
不会的,每个子类中 z 的值都是不同的。 - assylias
@assylias 抱歉。自然应该是这样的。 - user2651804
3个回答

4
与“每个实例一个”的实例变量不同,“静态”变量不是“每个子类一个”,而是“每个声明类一个”。换句话说,SuperClass 的子类共享 SuperClass.z,但不能按类别覆盖它。
这并不意味着您不能自行实现:一种实现每个子类存储整数的方法是向 SuperClass 添加一个 static Map<Class,int> zs,并提供可选的访问数据的函数。
public abstract class SuperClass {
    public int x, y;
    private static Map<Class,Integer> zs = new HashMap<Class,Integer>();
    protected static int getZ(Class c) {
        Integer res = zs.get(c);
        return res == null ? -1 : res.intValue();
    }
    protected static void setZ(Class c, int v) {
        zs.put(c, v);
    }
}
class SubClassOne extends SuperClass {
    public int getZ() {
        return SuperClass.getZ(SubClassOne.class);
    }
}
class SubClassTwo extends SuperClass {
    public int getZ() {
        return SuperClass.getZ(SubClassTwo.class);
    }
}

或者我可以在每个子类中都放置 public static int z = x。无论我想要多少个子类,这种方法不会比你的建议增加任何代码行数,对吧? - user2651804
@user2651804 这是正确的。唯一的区别在于,超类将无法轻松访问每个子类存储库中的 z - Sergey Kalinichenko
在我的情况下,我不需要这个。我一直计划通过引用SubclassA.z、SubclassB.z等来从外部类访问z值。我可能有一些可怕的设计缺陷:P - user2651804

3

可能最好的方法是在抽象类中添加一个z()方法或类似方法,然后在你想要的子类中重写该方法。

示例:

public abstract class SuperClass {
  public int x, y;

  protected int z() {
     return 42; // protected so only subclasses can see it - change if required
  }
}


public class SubClassOne extends SuperClass {

  public void foo() {
    // do something...
    int z = z();
    // something else...
  }
}

public class SubClassTwo extends SuperClass {

  @Override
  protected int z() {
    return 1;
  }

  // use z() accordingly
}

1
我认为这就是提问者想要的东西。我会向类中添加公共静态字段,这样我就不需要实例来检索字段了。现实世界中使用此方法的一个例子是Antlr:Lexerpublic abstract String[] getTokenNames();,子类有public static final String[] tokenNames = {...};并实现该方法。 - Silly Freak
@SillyFreak 嗯,他的SubClassTwo所做的正是我想要实现的 - 只是以更聪明的方式,但似乎不可能。 它也无法击败public static z = 1,那么为什么要写不必要的代码呢? - user2651804
1
这两者之间在动态绑定方面有非常重要的区别。考虑两个实例 SuperClass sup; SubClass sub;,以及一个访问 z 的非静态方法 SuperClass.foo()SuperClassSubClass 都声明了 static int z;sup.foo();sub.foo(); 都将使用 SuperClass.z,因为它们是静态绑定。你可能期望的行为是,所访问的 z 取决于对象的身份,而不是 foo() 所在的类。如果这就是你想要的,那么没问题,但一定要非常清楚地记录这个决定;否则可能会让其他开发人员感到困惑。 - Silly Freak
傻瓜Freak - 这是一个很好的观点。一般来说,我不喜欢静态,因为测试原因,但在这种情况下,它可能是合理的。 - manub

0

如果我理解你的意思是这样的话,那么就执行

public abstract class SuperClass {

  public int x, y, z;
  public SuperClass(int z) {

    this.z = z;

  }

}   

那么任何继承此类的类都会继承z;


可能甚至需要为 z 创建一个获取器和设置器。 - implements FeatheredOrcian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接