我让我的代码尽可能通用,以便在将来尝试帮助人们。我的抽象类有一个类类的方法和类型类的输入。在扩展抽象的类中,我尝试实现该方法无济于事。我做错了什么?
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
}
答案 0 :(得分: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 :(得分:2)
参数的类型和编号应保留。返回类型(如果它是基本类型)应保持相同,但如果它是引用类型,则它可以是子类类型。
在您的情况下,将此public B method1(B arg) { "...insert code here"}
更改为public B method1(A arg) { "...insert code here"}
答案 2 :(得分:2)
考虑more:为了与超类无法区分,子类必须接受超类所具有的所有相同参数;并返回超类可能的内容。
另一种说法是子类方法可以:
返回超类方法的更具体的类型(因为这是超类可能返回的值);例如,如果超类返回Object
,则子类可以返回String
,因为所有String
都是Object
s。
这称为协变返回类型,在Java中是允许的。子类不仅可以返回更具体的返回类型,还可以抛出比超类更具体的已检查异常;但他们也可以不声明他们抛出超类方法抛出的已检查异常。
接受比超类方法更通用的类型(因为这允许子类接受超类所有的参数)。
这将被称为逆变参数类型;但它在Java中不允许 。原因是在Java中选择了重载的方式:遗憾的是,方法签名(包括参数类型,但不包括返回类型)必须相同。
< / LI>语言规范的相关部分为Liskov substitution principle。
您的问题是使参数类型B
:这是更多特定于A
,因此B
的实例不可替代实例A
,因为A.method1
接受参数A
,而B.method1
则不接受。{/ 1>
让B.method1
获取A
类型的参数。
答案 3 :(得分:0)
Accept
的合同意味着A.method1
的每个对象都必须有A
,可以接受任何method1
个对象。
如果是A
,则可以使用B.method1
个对象,但不能使用其他B
。
答案 4 :(得分:0)
你写的每一件事都是正确的,除了重叠的方法参数类型,你不能在重写子类时改变超类抽象方法的签名。
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
}