web-dev-qa-db-ja.com

インターフェースを直接実装するか、スーパークラスに実装させる必要がありますか?

違いはありますか

public class A extends AbstractB implements C
{...}

対...

public class A extends AbstractB
{...}
abstract class AbstractB implements C
{...}

どちらの場合も、クラスAがインターフェイスに準拠することになることを理解しています。 2番目のケースでは、AbstractBCのインターフェースメソッドの実装を提供できます。それが唯一の違いですか?

インターフェイスメソッドの実装を提供したくない場合AbstractBどのスタイルを使用する必要があるか?どちらかを使用すると、「ドキュメント化」の目的が隠されますか?

14
c_maker

それはすべてAbstractB implements Cが意味論的にかどうかに依存します。つまり、AbstractBCを実装することが意味的に意味をなす場合は、それを実行します。

具体的な例を挙げると、意味の違いが明らかになります。

A =犬、AbstractB =動物、C = IBarkの場合

意味のある唯一の選択は

class Dog extends Animal implements IBark{

これは、すべての動物が吠えることを意味するため、意味がありません。

class Animal implements IBark{

AbstractBからclass Aを継承するだけではない場合、他の違いが関係します。 #1ではCを実装する必要はなく、#2ではすべてCを実装する必要があります。

20
Karthik T

これは「隠された」文書化の目的ではありません。 AbstractBとそのすべてのサブクラスをCにキャストできます。実際には3つのスタイルがあります。

public class A extends AbstractB implements C
public class AbstractB

AbstractBが論理的にCを実装していない場合は、これを使用します。メソッドが提供されていなくても、意味がある可能性があります。 Dogなどは、AnimalはWagを実装します。 Wagにとって、すべての動物にとって意味がありません。このアプローチは、AbstractBが実装を提供することを実際に妨げるものではないことに注意してください。

public class A extends AbstractB
public AbstractB implements C

すべてのサブクラスにインターフェースを実装させたいのであれば、これを使用しますが、すべてのサブクラスがそうすることが理にかなっています。 BeagleのようなAbstractDogはWagを実装しています。

public class A extends AbstractB implements C
public class AbstractB implements C

これは冗長ですが、明快さを追加するかもしれません。

2
Jeanne Boyarsky

適切な継承関係を判断する簡単な方法は、クラス自体ではなく、それらのクラスのcallsメソッドをコードで確認することです。コードのどこかにAbstractB b = new A();otherObject.addAbstractB(this);のようなものがあります。どちらの方法でも、後でそのAbstractB参照を使用してさまざまなメソッド呼び出しを行います。

その場合、Cのメソッドを呼び出しますか?その場合、AbstractBCを実装する必要があります。そうでない場合は、そうすべきではありません。そのような状況がない場合は、継承は不要であり、結合がはるかに緩いため、代わりにコンポジションを使用するようにリファクタリングする必要があります。

2
Karl Bielefeldt