我正在尝试通过蚂蚁将其作为泛型实现一个抽象超类Race,以便为蚂蚁访问诸如“ Movement Speed”之类的属性。对于不同的种族,我将创建扩展Race的类,并且显然我想为每个Race提供不同的属性。 “运动速度”必须以某种方式在Race中是静态的,因此我可以通过Class而不是对象的实例来访问它们,但是它不能是静态的,因为对于所有种族而言,它都是相同的。我需要一种解决此问题的方法,因为我的整个程序结构都依赖于此。

我不能使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;
    }
}


当我这样尝试时,在所有比赛中都一样,尽管不应该这样。

最佳答案

在某种程度上,“运动速度”在Race中必须是静态的,因此我可以按班级访问它们


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

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


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

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

除此之外,关于泛型的想法在这里不太适合。泛型(或多或少)关于“包含”某物。当您说class Foo<T extends Bar>时,您便表示Foo实例将以某种方式拥有/关联到Bar类。是的,以某种方式适合您的用例,但是(个人),我不确定泛型是否是此处的正确选择。

事实是:泛型通常是编译时的事情。在运行时,R的概念消失了。您的班级Ant不知道您是否有

Ant<Drone> ant = new Ant...


要么

Ant<Queen> a2 = ...


换句话说:R.speed从概念上讲是不可能的。更加面向对象的方法如下所示:

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实例化Ant。

另一方面,BaseAnt类对Ants执行所有“常见”的操作,然后您的子类添加特定的行为。

关于java - 抽象父类(super class)中静态变量的替代方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57945690/

10-09 19:22