使用泛型参数覆盖方法

时间:2016-01-13 14:54:37

标签: java generics inheritance type-erasure

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

我收到以下错误

“Rabbit不是抽象的,不会覆盖Animal”

中的抽象方法act(java.util.List<Actor>)

我认为狐狸兔的行为方法会覆盖动物和演员中的行为方法。我该如何解决这个问题?

以下是Actor类

中的抽象方法
abstract public void act(List<Actor>newActors);

然后使用以下代码

在Animal类中重写此方法
abstract public void act(List<Actor> newAnimals);

然后在兔子和狐狸类中使用以下方法覆盖此方法,这是出现错误的地方。

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

3 个答案:

答案 0 :(得分:4)

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

您可以在整个类层次结构中使用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>());

答案 1 :(得分:1)

您需要检查方法签名。当签名等于要覆盖的方法的签名时,方法将被覆盖。而act(List<Animal>)是一个与act(List<Actor>)不同的签名,因此你没有覆盖它。尝试在@Overrideact类中的rabbit方法之前应用fox,您会发现编译错误(因为它没有覆盖)。

如果您想要覆盖它,只需将方法更改为act(List<Actor>)rabbit类中的fox

答案 2 :(得分:0)

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

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

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