2008-12-09 114 views
7

我有一个接口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() { 
     // ... 
    } 
} 

我的代码工作正常,但我有几个问题:

  • 我应该声明抽象方法DOX()B类?为什么不)?

  • 我是否还应该在类C和D上显式声明“implements A”?为什么不)?

回答

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() { 
       // ... 
     } 
} 

你不应该混合与实现接口(方法签名)。

+0

此解决方案的好处是,当实现Z的类X实现时,需要方法commonY的功能,它可以专用类B. – 2008-12-09 11:59:03

4
  • 我应该声明的抽象方法DOX()在B类?为什么不)?

不是。它是一个抽象类 - 定义接口意味着所有的子类都需要实现这些方法。换句话说,这是多余的。

  • 我是否也应该在类C和D上显式声明“implements A”?为什么不)?

不,再次 - 因为您的超类(抽象基类)实现了该接口,您的具体子类将保证实现该接口。

0

实现接口的抽象类必须实现该接口。具体而言,它必须为该接口中指定的每个方法名称和签名提供公共方法。

继承是可传递的。如果C类派生了实现接口A的类B,则不需要编写该类实现接口A.但是,它也没有太大的危害。

+0

我不认为抽象类必须实现接口中的每个方法。我刚刚测试过这个,看起来你可以在抽象类中实现一个接口,而不需要实际声明任何接口的方法。 – 2008-12-09 11:48:44

+0

嗯,你可能是对的。我正在离开我对Java的记忆以及我目前在C#中的经验。在C#中,需要一个实现接口的抽象类来实现所有接口方法(即使只是将它们标记为抽象)。 – yfeldblum 2008-12-09 12:16:06

0

我不会B声明doX()因为你应该not repeat yourself不是CD添加“implements A”。

B中的摘要doX()什么也没加,因为它已经由“implements A”指定。将“implements A”添加到CD也是如此。

对这些条款的唯一可能的用途是文档:如果你想让它非常明确的是C(或D)是-A A,那么你可以添加implements,但你应该知道,它确实没有按对编译器无关紧要。

1

我只是抛出另一种选择。

将抽象类B转换为未实现A的AUtil类。方法签名可能需要类型A的附加参数才能使用。

C和D实现A,并在内部实例化一个AUtil。这确实允许C和D扩展其他类。

1

我同意JeeBee:考虑在抽象基类以外的地方实现你的帮助器方法。

如果您的帮助器方法commonY()仅存在于抽象基类B中,那么实现接口A的所有类也必须扩展基类B以利用commonY()的实现。但是,您可能并不总是希望被迫扩展B级。

另外,如果您想在将来更改commonY()的实现,该怎么办?然后,您将影响接口A的大量实现。但是,如果您不控制接口A的所有这些实现,则可能会影响其功能(糟糕的方式)而无意。

在这种情况下使用抽象基类可能会简单地带走一些灵活性,而不会给你任何回报。