違いはありますか
public class A extends AbstractB implements C
{...}
対...
public class A extends AbstractB
{...}
abstract class AbstractB implements C
{...}
どちらの場合も、クラスAがインターフェイスに準拠することになることを理解しています。 2番目のケースでは、AbstractB
はC
のインターフェースメソッドの実装を提供できます。それが唯一の違いですか?
インターフェイスメソッドの実装を提供したくない場合AbstractB
、どのスタイルを使用する必要があるか?どちらかを使用すると、「ドキュメント化」の目的が隠されますか?
それはすべてAbstractB implements C
が意味論的にかどうかに依存します。つまり、AbstractB
がC
を実装することが意味的に意味をなす場合は、それを実行します。
具体的な例を挙げると、意味の違いが明らかになります。
A =犬、AbstractB =動物、C = IBarkの場合
意味のある唯一の選択は
class Dog extends Animal implements IBark{
これは、すべての動物が吠えることを意味するため、意味がありません。
class Animal implements IBark{
AbstractB
からclass A
を継承するだけではない場合、他の違いが関係します。 #1ではCを実装する必要はなく、#2ではすべてCを実装する必要があります。
これは「隠された」文書化の目的ではありません。 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
これは冗長ですが、明快さを追加するかもしれません。
適切な継承関係を判断する簡単な方法は、クラス自体ではなく、それらのクラスのcallsメソッドをコードで確認することです。コードのどこかにAbstractB b = new A();
やotherObject.addAbstractB(this);
のようなものがあります。どちらの方法でも、後でそのAbstractB
参照を使用してさまざまなメソッド呼び出しを行います。
その場合、C
のメソッドを呼び出しますか?その場合、AbstractB
はC
を実装する必要があります。そうでない場合は、そうすべきではありません。そのような状況がない場合は、継承は不要であり、結合がはるかに緩いため、代わりにコンポジションを使用するようにリファクタリングする必要があります。