【问题标题】:Overriding methods with generic parameters使用泛型参数覆盖方法
【发布时间】:2016-01-13 14:54:36
【问题描述】:

我介绍了一个抽象的actor类,它是抽象动物类的子类。我现在面临的问题是 Rabbit 类(动物的子类)中的 act 方法不起作用。

我收到以下错误

“Rabbit 不是抽象的,不会覆盖 Animal 中的抽象方法 act(java.util.List<Actor>)

我认为 Fox 中 rabbit 中的 act 方法会覆盖 Animal 和 Actor 中的 act 方法。我该如何解决这个问题?

下面是Actor类中的抽象方法

abstract public void act(List<Actor>newActors);

然后用下面的代码在 Animal 类中重写此方法

abstract public void act(List<Actor> newAnimals);

然后在 rabbit 和 fox 类中使用以下方法覆盖此方法,这就是错误出现的地方。

  public void act(List<Animal> newRabbits)
    {
        incrementAge();
        if(isAlive()) {
            giveBirth(newRabbits);            
            // Try to move into a free location.
            Location newLocation = getField().freeAdjacentLocation(getLocation());
            if(newLocation != null) {
                setLocation(newLocation);
            }
            else {
                // Overcrowding.
                setDead();
            }
        }
    }

【问题讨论】:

    标签: java generics inheritance type-erasure


    【解决方案1】:

    List 的参数化类型是这里的问题,因为它在运行时被擦除(参见type erasure),因此会破坏虚拟方法调用。

    您可以在整个类层次结构中使用 List&lt;? extends Actor&gt; 参数化您的方法以解决此问题。

    以下内容:

    class Actor {
    
    }
    class Animal extends Actor {
    
    }
    abstract class Abstract {
        abstract void act(List<? extends Actor> actors);
    }
    class Child extends Abstract {
        @Override
        void act(List<? extends Actor> actors) {
            // TODO something
        }
    }
    

    然后您使用以下行中的某些内容调用它:

    new Child().act(new ArrayList<Animal>());
    

    【讨论】:

      【解决方案2】:

      您需要检查方法签名。当签名等于要覆盖的方法的签名时,方法将被覆盖。而act(List&lt;Animal&gt;)act(List&lt;Actor&gt;) 是不同的签名,因此您没有覆盖它。尝试在 rabbitfox 类中的 act 方法之前应用 @Override,您会注意到编译器错误(因为它没有被覆盖)。

      如果您想覆盖它,只需在 rabbitfox 类中将方法更改为 act(List&lt;Actor&gt;)

      【讨论】:

      • 完美的工作,|很困惑,因为我认为 Animal 类调用了 Actor 类,而 rabbit 和 fox 类调用了 animal 类,再次感谢! @凯文
      【解决方案3】:

      如前所述,编译器需要找到与抽象类中签名相同的方法。

      另一种解决方案是这样做:

      abstract class Actor<T extends Actor> {
          public abstract void act(List<T> actors);
      }
      abstract class Animal<T extends Animal> extends Actor<T> {
      }
      class Rabit extends Animal<Rabit> {
          @Override
          public void act(List<Rabit> actors) {
              // TODO 
          }
      }
      

      这将避免将 Girafe 作为 Rabit 类的参数传递:

      class Girafe extends Animal<Girafe> {
           ...
      }
      
      
      new Rabit().act(new ArrayList<Rabbit>()); // It's OK
      new Rabit().act(new ArrayList<Girafe>()); // won't compile
      

      【讨论】:

        猜你喜欢
        • 2020-06-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多