使用通用参数覆盖方法
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>)
不同的签名,因此您没有覆盖它。尝试在 rabbit
和 fox
class 中的 act
方法之前应用 @Override
,您会注意到编译器错误(因为它没有被覆盖)。
如果您想覆盖它,只需在 rabbit
和 fox
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
我介绍了一个抽象演员 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>)
不同的签名,因此您没有覆盖它。尝试在 rabbit
和 fox
class 中的 act
方法之前应用 @Override
,您会注意到编译器错误(因为它没有被覆盖)。
如果您想覆盖它,只需在 rabbit
和 fox
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