想象一下,我有一个带有方法的抽象类Animal:
public abstract void fetch(Animal ani);
然后我有一个使用以下内容扩展这个抽象类的类:
public class GoldenRetriever extends Animal {
public void fetch(GoldenRetriever pup) {
pup.paws = "I have paws";
}
}
我希望每个扩展Animal的类都有一个fetch()方法。然而,获取方法为所讨论的动物分配了一些独特的特征(狗的爪子,猫的爪子等)。例如,cat的fetch()将获取参数fetch(FelineCat kitty)并说:
public void fetch(FelineCat kitty) { kitty.claws = "I have claws."; }
因此,fetch方法接受扩展抽象类Animal的参数(因此是动物)。我在Animal中定义了方法fetch()来获取Animal类型的任何参数。对我来说,这是有道理的,因为猫和狗是动物,但Java说GoldenRetriever无法覆盖抽象方法fetch(Animal ani)。为什么是这样?
答案 0 :(得分:1)
不确定我是否100%正确理解您的问题,但我认为我的问题有一些解决方案。以下代码有效,它可能不是最佳的,因为您总是必须使用泛型参数,但至少键入是正确的。
public abstract class Animal<T extends Animal> {
public abstract void fetch(T ani);
}
public class GoldenRetriever extends Animal<GoldenRetriever> {
@Override
public void fetch(GoldenRetriever ani) {
}
}
答案 1 :(得分:1)
该方法不会覆盖,因为参数类型不同。你必须声明这样的方法:
public class GoldenRetriever extends Animal {
public void fetch(Animal pup) {
即。参数类型仍然必须为Animal
,即使您正在编写一个扩展Animal
的类。
这是一个很好的理由。假设您有其他方法
public void someMethod(Animal x)
您可以将任何Animal
作为参数传递,包括GoldenRetriever
:
GoldenRetriever gr = ...;
someMethod(gr);
假设在someMethod
中你有这个:
public void someMethod(Animal x) {
FelineCat kitty;
...
x.fetch(FelineCat);
由于Animal
fetch
方法可以接受任何Animal
,因此编译器认为进行此调用必须正常,因为FelineCat
是Animal
x
。它无法知道GoldenRetriever
实际上是GoldenRetriever
。如果它允许覆盖方法采用FelineCat
参数,则会出现问题,因为参数实际上是GoldenRetriever
,而不是fetch
。那么当多态地调用x
时,参数类型是错误的,那么呢?
编译器无法阻止这种情况,因为它无法知道ClassCastException
的类型是什么。从理论上讲,Java 可以允许覆盖更改参数类型,并在运行时进行检查(如果它试图让GoldenRetriever
获取其他某些内容,可能会抛出Animal
有点public class GoldenRetriever extends Animal {
public void fetch(Animal pup) {
if (pup instanceof GoldenRetriever) {
GoldenRetriever puppy = (GoldenRetriever)pup;
// now puppy is viewed as a GoldenRetriever, and any methods or
// instance variables particular to GoldenRetrievers can be accessed
} else {
throw new WrongSpeciesException("..."); // or whatever
}
}
}
)。我不知道为什么他们没有,但我确信有充分的理由不这样做。
但是你可以进行自己的运行时检查:
public void fetch(GoldenRetriever pup)
更新:上述答案假定方法签名确实是您想要的。但是根据Mixone的评论,可能是你不尝试设置涉及两只动物的操作,在这种情况下你不应该有参数所有。像
这样的方法GoldenRetriever
假设您有一个GoldenRetriever
将与另一个GoldenRetriever
做某事,并且您不希望int a, b;
a = 7;
b = 2;
std::cout << a / b << std::endl;
与其他种类的动物一起做。在这种情况下,我认为运行时检查是最好的方法。但是,如果你想要一个只对一只动物起作用的手术,你就写错了。
答案 2 :(得分:0)
覆盖另一个方法的方法必须具有完全相同的参数,否则称为重载。
您的fetch
方法必须声明如下:
public void fetch(Animal ani)
答案 3 :(得分:0)
您可以将Animal
类设为通用类,例如
abstract class Animal<TAnimal extends Animal<?>> {
public abstract void fetch(TAnimal ani);
}
class GoldenRetriever extends Animal<GoldenRetriever> {
String paws;
@Override
public void fetch(GoldenRetriever pup) {
pup.paws = "I have paws";
}
}
答案 4 :(得分:0)
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package fetchanimal;
/**
*
* @author Amin
*/
public abstract class Animal <T>{
public abstract void fetch(T animalType);
}
现在创建一个新类
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package fetchanimal;
/**
*
* @author Amin
*/
public class FelineCat extends Animal<FelineCat> {
public String claws ;
@Override
public void fetch(FelineCat animalType) {
// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
animalType.claws = "hello";
}
}
现在创建第三个类
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package fetchanimal;
/**
*
* @author Amin
*/
public class GoldenRetriever extends Animal<GoldenRetriever>{
public String paws ;
@Override
public void fetch(GoldenRetriever animalType) {
// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
animalType.paws = "hello" ;
}
}
只需复制粘贴代码
即可