使用通用参数覆盖方法

Overriding methods with generic parameters

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

我收到以下错误

"Rabbit is not abstract and does not override abstract method act(java.util.List<Actor>) in Animal"

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

下面是Actor中的抽象方法Class

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

然后使用以下代码在 Animal class 中覆盖此方法

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

此方法随后在 rabbit 和 fox classes 中被以下内容覆盖,这就是错误出现的地方。

  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();
            }
        }
    }

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

您可以在整个 class 层次结构中使用 List<? extends Actor> 参数化您的方法来解决此问题。

行中的内容:

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>());

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

如果您想覆盖它,只需在 rabbitfox class.

中将方法更改为 act(List<Actor>)

如前所述,编译器需要找到一个与摘要中具有相同签名的方法class。

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

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 :

class Girafe extends Animal<Girafe> {
     ...
}


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