2017-02-18 133 views
4

我尽可能地使我的代码尽可能通用,以尝试和帮助未来的人。我的抽象类有一个类型类的方法和一个类型类的输入。在扩展抽象的类中,我试图实现该方法无济于事。我究竟做错了什么?在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 
} 
+3

参数必须是“A”型。 –

+0

该方法的参数是否必须与子类(在您的示例'B')中具有相同的确切类型? –

+0

是的。 B.method1中只有在B中需要的方法。 –

回答

3

达到你想要的一切:参数的类型来声明类相关联,您可以使用泛型。

抽象类:

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 ... 
    } 
} 
+1

这会产生警告,因为'A'是通用的,在'''A'不是。你应该修正它如下:'>' –

+1

@Federico Peralta Schaffner确实,谢谢:) – davidxxx

0

A.method1合同意味着每个对象,它是一个A必须具有method1可采取任何A对象。

B.method1的情况下,它可能需要B对象,但它不能接受另一个A

0

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

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

对不起@AndyTurner我写了返回类型而不是参数类型。谢谢你纠正我。 –

2

应保留参数的类型和编号。返回类型,如果它是原始类型,应保持相同,但如果它是引用类型,则它可以是子类型。

你的情况,这个变化对public B method1(B arg) { "...insert code here"}public B method1(A arg) { "...insert code here"}

2

想想Liskov substitution principle:为了从一个超类没有区别,子类必须接受所有相同参数的超类将;并返回超类可能

另一种方式把这是一个子类方法可以:

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

    这就是所谓的协变返回类型,并在Java中是允许的。子类不仅可以返回更具体的返回类型,还可以抛出比超类更多的特定检查异常;但他们也可以而不是声明它们抛出超类方法抛出的检查异常。

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

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

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

您的问题是使参数类型B:这是比A具体,所以B一个实例是不可替代为A一个实例,因为A.method1接受一个参数A,而B.method1没有。

品牌B.method1采用A型号的参数。