【问题标题】:Alternative for static variable in abstract supeclass抽象超类中静态变量的替代方案
【发布时间】:2019-09-15 15:44:48
【问题描述】:

我正在尝试创建一个抽象超类Race,它由我的蚂蚁作为通用实现,以便我可以访问蚂蚁的“移动速度”等属性。对于不同的种族,我将创建扩展Race 的类,并且显然我想为每个Race 赋予不同的属性。 “运动速度”在Race 中必须是静态的,所以我可以通过类而不是对象的实例来访问它们,但它不能是静态的,因为它对于所有种族都是一样的。我需要一种方法来规避这个问题,因为我的整个程序结构都依赖于它。

我不能让Race 成为Ant 的超类,因为我有Ant 的子类,例如DroneQueen,它们应该适用于所有种族。

public abstract class Race {
    public static double speed;
}

public class defaultAnt extends Race {
    public static double speed = 2;
}

public abstract class Ant<R extends Race> {
    public void move(){
           speed = R.speed;
    }
}

当我这样尝试时,所有种族都一样,尽管不应该这样。

【问题讨论】:

  • static 字段绑定到类而不是这些类的实例。
  • 嗨!当您提出问题时,文本区域右侧有一个很大的如何格式化框,其中包含有用的信息。还有一个工具栏,里面装满了格式化辅助工具。还有一个 [?] 按钮提供格式化帮助。 一个预览区域,显示您的帖子在发布时的样子,位于文本区域和“发布您的问题”按钮之间(因此您必须滚动过去才能找到该按钮,以获取你看它)。使您的帖子清晰,并表明您花时间这样做,可以提高您获得好答案的机会。这次我给你修好了。
  • 我只是在我的回答中给出了一个模糊的提示,你应该做什么而不是在这里使用静态。问题是:要给出更好的答案,我必须更好地理解您的问题。它的开头是:您是说“种族”之类的“物种”,还是您的意思是“种族”之类的“赛车比赛”?
  • 我知道静态意味着什么,我看到了问题,我正在寻找如何解决问题的想法,而对于种族,我的意思是物种,我认为这更明显

标签: java generics inheritance static


【解决方案1】:

“运动速度”需要以某种方式在 Race 中保持静态,以便我可以通过类访问它们

一点也不。将static 视为良好 OOP 设计中的异常,尤其是在 Java 中。 OOP 方法是这样的:

public abstract class Race {
  protected abstract double getIndividualSpeed();
...

然后子类(在正确的位置)@Override 以提供单独的速度。

但如前所述:这里的关键是您退后一步,重新思考您的设计。使用静态字段,尤其是在“多态”上下文中(几乎)是不行的。

除此之外,关于泛型的想法,在这里不太适合。泛型(或多或少)是关于“包含”某些东西的。当您说class Foo&lt;T extends Bar&gt; 时,您会传达 Foo 实例将以某种方式拥有/关联到 Bar 类。哪个,是的,某种程度上适合您的用例,但是(就个人而言),我不确定泛型是否是正确的选择。

问题是:泛型主要是编译时的事情。在运行时,R 的概念消失了。你的班级Ant不知道你有没有

Ant<Drone> ant = new Ant...

Ant<Queen> a2 = ...

换句话说:R.speed 在概念上是不可能的。更 OOP 的方法可能如下所示:

public abstract class BaseAnt<R extends Race> {
   protected final R rInstance;
   protected BaseAnt(R rInstance) { this.R rInstance = R rInstance; }

   public final double move(double distance) {
      return distance / Instance.getSpeed();
   }

public class Ant<R extends Race> {
  ctor that calls super constructor

然后

public enum Race {
  DRONE(5), QUEEN(1);

  private final double speed;
  private Race(double speed) { this.speed = speed; }

  public double getSpeed() { return speed; }

换句话说:您可以使用作为“常量提供者”的枚举。你可以在 Race.DRONE 上调用getSpeed();然后你回来5

然后您可以使用 Race.DRONE 或 Race.QUEEN 实例化 Ants。

另一方面,BaseAnt 类为 Ants 执行所有“通用”的东西,然后您的子类添加特定的行为。

【讨论】:

  • 感谢您的回答,我不知道我应该避免 OOP 中的静态问题。我认为 Race 是每个蚂蚁都有一个实例的对象,但我的整个设计都围绕着这个系统,所以我想我可能遗漏了一些东西,我可以在这里找到解决方案。老实说,我很高兴我(或多或少)理解了泛型并使用了它们:D
  • @Pht 重点是:你必须小心使用静态。它导致与其他类的直接耦合,并且在多态性方面具有不同的“语义”。
  • 我总是有一个“属性”类,它是抽象的,只包含静态最终变量,例如帧大小。我使用它,所以当我想更改如此基本的东西时,我不必在我的代码中搜索。我以为我可以这样做,但显然不是这样^^
  • 哦,哇,是的,非常感谢您的详细回答和您的时间!
  • @Pht 我很欣赏你的快速回归。如果您有第二个,请查看您的 cmets,看看其中一些是否可以删除。我们的想法是只留下对未来读者真正有帮助的内容,这样他们就可以专注于……嗯,有用的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-31
  • 1970-01-01
  • 1970-01-01
  • 2010-11-12
  • 1970-01-01
  • 2012-12-04
相关资源
最近更新 更多