2013-04-05 27 views
18

動物と犬という2つのクラスがあるとします。 DogはAnimalのサブクラスです。私は次のコードを実行します:多型対継承

Animal a = new Dog(); 

これで変数を使ってDogクラスのメソッドを呼び出すことができます。

私の質問はこれです:もし私が犬のオブジェクト(継承)を通じてAnimalのメソッドのすべてを呼び出すことができれば、なぜ多態性の原理を使うべきですか?私はちょうど宣言することができます:

Dog d = new Dog(); 

この宣言では、すべてのAnimalのメソッドとDogメソッドを使用できます。なぜ多型を使うのですか?ご回答どうもありがとうございました。

+1

質問のタイトル( "多相性対継承")は定義上間違っています:) – Poni

+0

[相続と多型の主な相違点は何ですか?](http://stackoverflow.com/questions/6308178/what-継承と多型の間の主な違いです) – tstew

答えて

23

Javaでは、多型と継承の概念は「溶接」されるために動作しないであろう。一般的に、それはそのようにする必要はありません。

  • 多型は、クラスの正確な型
  • 継承は、派生クラスのシェアインタフェースとその基底クラスのコードをすることができますを知らなくても、あなたはクラスのメソッドを呼び出すことができます

は継承が多型から分離された言語がある:(あなたが多型の挙動を生じることなくクラスを継承することができますC++では

  • すなわちありませんvirtualを持つ基底クラスのmark関数)
  • Objective Cでは、無関係のクラスに対してメソッドを実装し、メソッドのシグネチャのみを知っている場所から呼び出すことができます。バックからJavaへ行く

、多型を使用する理由は、そのカウンターパーティの実装の詳細からあなたのコードをデカップリングされています。たとえば、あなたが動物のすべての種類のために働く方法Feed(Animal animal)を書くことができれば、このメソッドは、Animalのサブクラスまたは実装を追加するときに適用されます。これは、犬に密接に結合されるFeed(Dog dog)方法とは対照的である。

限り

Dog d = new Dog(); 

宣言が行くように、あなたはあなたの方法の残りの部分は犬と特異的に扱うことがわかっている場合はこれを回避するという一般的な理由はありません。しかし、多くの場合、後にはそうではありません。例えば、あなたのクラスや、あなたの方法は、しばしばそのような場合には例

List<Integer> numbers = new ArrayList<Integer>(); 

ため、正確な実装に鈍感になり、あなたは、new LinkedList<Integer>()new ArrayList<Integer>()を置き換えることができますのコードをコンパイルすることを知っています。対照的に、numbersリストがArrayList<Integer> numbersと宣言されていた場合、そのような切り替えは確実ではなかった可能性があります。

これは「インターフェイスへのプログラミング」と呼ばれます。それを説明するスタックオーバーフロー上の非常に良いanswerがあります。

+1

ありがとう、素晴らしい説明。 – Alan

4

Catのように、Animalクラスの他の実装を持つことができます。そして、あなたはそれが本当にあるの実装思いやりのあるなしAnimalクラスのメソッドを呼び出すことができ、かつが正しいメソッドを呼び出します

Animal a = new Dog(); 
Animal b = new Cat(); 

を言うことができます。例えば。

a.speak(); // "Woof" 

b.speak(); // "Meow" 

実際には、「多相性対継承」ではなく、「相続を使用する多形性」ではありません。この方法はまだ書かれていなければならないAnimalのサブクラスを含むなど、DogCatを受け入れるだろう

public void pet(Animal animal) { 
    ... 
} 

+0

まず、答えをありがとうございます。しかし、私はまだ私がただ宣言してはならない理由はありません:犬d =新しい犬(); Animal = new Dog();を使用する代わりに、私はまだAnimalのメソッドのすべてを使用できますか? – Alan

+0

'Dog'固有の機能が必要な場合は、必ず' Dog d = new Dog() 'を使用してください。 'Animal'特有の機能だけが必要なときの@ NPEの答えを見てください。このコードは、 'Animal'の実装には有効です。 – rgettman

+0

ありがとうございました! :)それは非常に有用です。 – Alan

4

多型は、あなたがどんなAnimalのために働く方法を記述することができます。

方法はDogを取るした場合、それはCat

+0

まず、お返事ありがとうございます。しかし、私はまだ私がただ宣言してはならない理由はありません:犬d =新しい犬(); Animal = new Dog();を使用する代わりに、私はまだAnimalのメソッドのすべてを使用できますか? – Alan

1

いつも犬になると確信しているなら、それは理由がありません。あなたも使用するかもしれない犬d =新しい犬();説明した通りしかし、コンストラクタの代わりにメソッドを使用したとしましょう。メソッドは動物を返し、あなたはどの動物の実装を取得するか分からない。あなたはまだ動物の同じ方法を使用することができます(たとえそれが犬、象の猫などであっても)。

拡張性の目的で、継承は事柄を単純化します。ゾウやネコをいくつかの動物の方法を共有したい場合は、動物をスーパークラスにすることで簡単に得ることができます。

+1

ありがとうございました! – Alan

0

通常、あなたが尋ねた質問は、継承対組成より似ています。より多くの「実生活」の例は、多形性を使用するのが良い理由の例です。たとえば、戦略デザインパターンの使用です。多くのTaxPolicyの実装を行うことができます:UsaTaxPolicy、CanadaTaxPolicy、EuTaxPolicyなど税金を計算する必要のあるcalculateFinalPriceメソッドがあれば、適切な実装を注入し、Usa、Canada、またはEuの実装。

0

継承は動的多型です。つまり、継承を削除すると、もうオーバーライドできなくなります。