繁体   English   中英

在Java中的子类中实现抽象方法

[英]Implementing abstract methods in a subclass in Java

我已经使我的代码尽可能通用,以便在将来尝试帮助人们。 我的抽象类有一个类类的方法和类型类的输入。 在扩展抽象的类中,我尝试实现该方法无济于事。 我究竟做错了什么?

public abstract class A {
    public abstract A method1(A arg);
}

public class B extends A {
    @Override
    public B method1(B arg) { "...insert code here"} // Error: The method method1(B) must override or implement a supertype method
}

要实现您想要的:将参数的类型与声明的类相关联,您可以使用泛型。

抽象类:

public abstract class A <T extends A<T>> {
    public abstract T method1(T arg);
}

具体课程:

public class B extends A<B> {
    @Override
    public B method1(B arg) { 
     ...
      return ...
    }
}

应保留参数的类型和否。 返回类型(如果它是基本类型)应保持相同,但如果它是引用类型,则它可以是子类类型。

在您的情况下,将此public B method1(B arg) { "...insert code here"}更改为public B method1(A arg) { "...insert code here"}

想想Liskov替换原则 :为了与超类无法区分,子类必须接受超类所具有的所有相同参数; 并返回超类可能的东西。

另一种方法是子类方法可以:

  • 返回超类方法的更具体的类型(因为这是超类可能返回的值); 例如,如果超类返回Object ,则子类可以返回String ,因为所有String都是Object

    这称为协变返回类型 ,在Java中是允许的。 子类不仅可以返回更具体的返回类型,还可以抛出比超类更具体的已检查异常; 但他们也不能声明它们抛出超类方法抛出的已检查异常。

  • 接受比超类方法更通用的类型(因为这允许子类接受超类所有的参数)。

    这将被称为逆变参数类型 ; 但它不是在Java的许可。 原因是在Java中选择重载的方式:遗憾的是,方法签名(包括参数类型,但不包括返回类型)必须相同

语言规范的相关部分是JLS Sec 8.4.8.3

您的问题是使参数类型为B :这比A 具体,因此B的实例不能替代A的实例,因为A.method1接受参数A ,而B.method1不接受。

使B.method1取一个A类参数。

A.method1的契约意味着作为A每个对象必须具有可以接受任何A对象的method1

B.method1的情况下,它可以采用B对象,但它不能采用另一个A

你写的每一件事都是正确的,除了重叠的方法参数类型,你不能在重写子类时改变超类抽象方法的签名。

public abstract class A {
    public abstract A method1(A arg);
}

public class B extends A {
    @Override
    public B method1(A arg) { "...insert code here"} // Error: The method method1(B) must override or implement a supertype method
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM