我有一个接口A,我必须提供一些不同的接口 实现。但是,这些实现共享一些辅助方法,所以 我将这些方法移动到一个抽象基类。
Interface A {
void doX();
}
abstract Class B implements A {
protected void commonY() {
// ...
}
@Override
public abstract void doX();
}
Class C extends B {
@Override
public void doX() {
// ...
}
}
Class D extends B {
@Override
public void doX() {
// ...
}
}
我的代码按预期工作,但我有几个问题:
我应该在B类中声明抽象方法doX()吗?为什么(不是)?
我是否还应该在C类和D类上明确声明“实现A”?为什么(不是)?
答案 0 :(得分:8)
我认为按照以下方式做得更好:
Interface A {
void doX();
}
abstract Class B {
protected void commonY() {
// ...
}
}
Class C extends B implements A{
public void doX() {
// ...
}
}
Class D extends B implements A{
public void doX() {
// ...
}
}
您不应该将接口(方法的签名)与实现混合在一起。
答案 1 :(得分:4)
没有。它是一个抽象类 - 定义接口意味着所有子类都需要实现这些方法。换句话说,这是多余的。
不,再次 - 因为您的超类(抽象基类)实现了该接口,您的具体子类将保证实现该接口。
答案 2 :(得分:1)
我会抛出另一个选项。
将抽象类B转换为未实现A的AUtil类。方法签名可能需要使用类型A的附加参数。
C和D实现A,并在内部实例化AUtil。这确实允许C和D扩展其他类。
答案 3 :(得分:1)
我同意JeeBee:考虑在除抽象基类之外的某个地方实现辅助方法。
如果你的辅助方法commonY()只存在于抽象基类B中,那么实现接口A的所有类也必须扩展基类B,以便利用commonY()的实现。但是,您可能并不总是希望被迫扩展B类。
此外,如果您希望将来更改commonY()的实现,该怎么办?然后,您将影响接口A的许多实现。但是,如果您不控制接口A的所有这些实现,则可能会影响它们的功能(以一种糟糕的方式)而不打算这样做。
在这种情况下使用抽象基类可能会带来一些灵活性,而不会给你任何回报。
答案 4 :(得分:0)
实现接口的抽象类必须实现该接口。具体来说,它必须为该接口中指定的每个方法名称和签名都有一个公共方法。
继承是传递性的。如果类C派生实现接口A的类B,则不需要编写类C实现接口A.但是,它也没有太大的危害。
答案 5 :(得分:0)
我不会在doX()
中声明B
,也不会在implements A
和C
上添加“D
”,因为您应该not repeat yourself。< / p>
doX()
中的摘要B
不会增加任何内容,因为它已由“implements A
”指定。将“implements A
”添加到C
和D
也是如此。
这些条款唯一可能的用途是文档:如果你想明确C
(或D
)是一个A
,那么你可以添加implements
,但你应该知道它对编译器来说无关紧要。