当前位置: 首页 > 知识库问答 >
问题:

继承具有不同参数类型的抽象方法的抽象类

左华灿
2023-03-14

想象一下,我有一个抽象类动物的方法:

public abstract void fetch(Animal ani);

然后我有一个类,用以下内容扩展这个抽象类:

public class GoldenRetriever extends Animal {
       public void fetch(GoldenRetriever pup) { 
             pup.paws = "I have paws"; 
       }
}

我希望每个扩展Animal的类都有一个fetch()方法。然而,fetch方法为相关动物指定了一些独特的特征(狗的爪子、猫的爪子等)。例如,cat的fetch()将获取参数fetch(fellinecat kitty)并表示:

public void fetch(FelineCat kitty) { kitty.claws = "I have claws."; }

因此,抓取方法接受了扩展抽象类“动物”(因此是动物)的参数。我在“动物”中定义了抓取()方法,以接受任何类型“动物”的参数。对我来说,这是有意义的,因为猫和狗都是动物,但是Java说黄金寻回器未能覆盖抽象方法抓取(动物)。这是为什么?

共有3个答案

聂炜
2023-03-14

重写另一个方法的方法必须具有完全相同的参数,否则它被称为重载。您的抓取方法必须这样声明:

public void fetch(Animal ani)
韩夕
2023-03-14

该方法不会重写,因为参数类型不同。您必须这样声明方法:

public class GoldenRetriever extends Animal {
    public void fetch(Animal pup) { 

也就是说,参数类型仍然必须是动物,即使您正在编写一个扩展动物的类。

这是有充分理由的。假设你有其他方法

public void someMethod(Animal x) 

您可以传递任何动物作为参数,包括一个GoldenRetriever

GoldenRetriever gr = ...;
someMethod(gr);

假设在someMethod中,您有这样一个:

public void someMethod(Animal x) {
    FelineCat kitty;
    ...
    x.fetch(FelineCat);

由于Animalfetch方法可以接受任何Animal,编译器认为进行此调用必须是可以的,因为FelineCatAnimal。它无法知道x实际上是GoldenRetriever。如果它允许重写方法采用GoldenRetriever参数,则会出现问题,因为该参数实际上是FelineCat,而不是GoldenRetriever。那么当多态地调用fetch时,参数类型是错误的,那又怎样呢?

编译器没有办法阻止这一点,因为它没有办法知道x的类型是什么。理论上,Java可以允许重写更改参数类型,并在运行时进行检查(如果它试图获取GoldenRetriever来获取其他类型的动物,可能会抛出ClassCastExctive)。我不知道他们为什么没有,但我确信有很好的理由不这样做。

但您可以自己进行运行时检查:

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
        }
    }
}

更新:以上答案假设方法签名是您真正想要的。但在Mixone的评论之后,可能是您没有试图设置涉及两种动物的操作,在这种情况下,您根本不应该拥有该参数。像这样的方法

public void fetch(GoldenRetriever pup)

假设你有一个GoldenRetriever将与另一个GoldenRetriever一起做某事,而你只是不想让一个GoldenRetriever与其他种类的动物一起做。在这种情况下,我认为运行时检查是最好的方法。但如果你想要一个只对一只动物有效的手术,那你就写错了。

夏骞尧
2023-03-14

不确定我是否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) {

    }
}
 类似资料:
  • 我有一个关于JPA中继承的问题,是否可以使用JOINED策略来实现这个层次结构? 这是我的代码: 在上面的层次结构之后,我尝试使用JPQL进行查询,这是查询: 此代码从主代码运行 当我运行该查询时,会抛出以下错误 导致原因:com . MySQL . JDBC . exceptions . JDBC 4 . MySQL syntaxerrorexception:未知列“employee1_。“字段

  • 继承一个可以实现的普通超类有什么不同吗? atm我有一个名为的抽象类,我有/扩展这个。 abstractcar中的一个字段设置为"私有int容量" 但是在子类“小型汽车”中,当我输入“容量”作为构造函数中使用的变量时,它说“容量在抽象汽车中有私有访问” 我想: > 子类继承超类的所有字段和方法? 我现在该怎么进行?

  • 我有一个抽象类,这个类是在她的子类中扩展的: < li >我在这个抽象类上实现了一个方法,并抽象了另一个方法 < li >实现的方法是每个子类对象都必须访问的通用方法。所以我决定在抽象类上实现它,避免在每个子类上实现相同的方法。 小例子: 我想听听你对这种实施方式的看法, 问候。

  • 所以,问题是:我有一个抽象基类(),它有一个抽象成员方法()。方法返回布尔值,并应检查是否相等,但“相等”在子类中可能有不同的解释,因此我不重写或。因为它测试是否与另一个与其类型相同的对象相等,所以签名如下所示: 现在,当我试图在类中重写它时,假设“”,我不能使用作为参数的类型。我知道一般情况下这样做的原因和添加类型界限的建议,但是事情变得更加复杂,因为参数类型是它自己的类。 有没有什么平滑的方法

  • 我有2个抽象的类操纵泛型和一个工厂与泛型。父级独立于trips对象和因式分解代码。儿子只基于trips。 Eclipse上的AbstractTripBasedPurchaseExtractor第9行出现错误:Bound mismatch:类型TRIP_PURCHASE不是bounded参数的有效替代品 类型的 此处:extends AbstractPurchaseExtractor“ 在son类上

  • 问题是: 我有一个叫做Schema的基类,它是抽象的,它是一个未生成的类。我有两个从Schema继承生成的JAXB类:FixedWidthSchema和DelimitedSchema。 我使用外部绑定(xjb)文件来指定XSD和Java类之间的映射。 在基类模式中,我定义了几个方法: 公共架构静态创建(Model m),它从提供的模型创建架构。 公共抽象Writer marshal(),它将当前架