継承とポリモーフィズムの主な違いは何ですか?


172

今日、モジュールの終わりに開かれた本の試験でこの質問が出され、私は迷っていました。私は読んでいてHead first Java、両方の定義がまったく同じであるように見えました。自分の心の中での主な違いは何だろうと思っていました。これと同様の質問がいくつかあることは知っていますが、決定的な答えを提供するものはありません。


2
:どういうわけかこの質問に関連した継承せずに多型が可能です
エドウィンDalorzo

回答:


289

継承とは、「クラス」が既存の「クラス」から派生する場合です。したがって、Personクラスがある場合Student、拡張するクラスがありPerson、そのすべてのものをStudent 継承Personます。Personのフィールド/メソッドに配置するアクセス修飾子の周りにいくつかの詳細がありますが、それは基本的な考え方です。たとえば、にプライベートフィールドがある場合PersonStudentそのプライベートので、それを見ていない、とプライベートフィールドは、サブクラスには見えないだろう。

ポリモーフィズムは、プログラムの種類に応じて、使用するメソッドをプログラムがどのように決定するかを扱います。お持ちの場合はPerson持っている、read方法を、あなたは持ってStudent延びているPersonの独自の実装有している、readあなたが持っている場合によっては、ランタイムがあなたのために決定されて呼び出されるメソッド、PersonまたはStudent。少しトリッキーになりますが、次のようなことをすると

Person p = new Student();
p.read();

Studentのreadメソッドが呼び出されます。それは実際の多型です。a Student はである ため、この割り当てを行うことができますPersonが、ランタイムはの実際のタイプpStudentであることを認識するのに十分スマートです。

詳細は言語によって異なります。たとえば、JavaScriptで継承を行うことができますが、Javaでの動作とはまったく異なります。


9
つまり、スーパークラスとサブクラスの関係は継承であり、親クラスとそのサブクラスの間で異なる方法で同じメソッドを実装するという概念であり、状況に基づいてそれらを呼び出すのがポリモーフィズムです。私は正しいですか?
Muhammad Raihan Muhaimin 2013年

1
@hvgotcodesしかし場合と言うPersonread方法は、パブリックアクセス修飾子を使用しているが、しませんStudentそれらにアクセスできるようにオブジェクト?そして、それStudent s = new Student();は簡単ではないでしょうか?私はまだ実際に多形主義の利点を実際にはあまり得ていません。
Scorpiorian83 2017

1
@hvgotcodes Student s = new Student()は機能します。しかし、このアイデアを使用して多くのコードを記述した後、後で間違いを見つけたとしましょう。その人は実際には学生ではなく、教師です。したがって、Person p = new Student()からPerson p = new Teacher()に変更するだけで、人生がずっと簡単になります。
munmunbb 2017

ここで私の質問は、なぜあなたはPerson p = new Student();代わりに使用したいのStudent p = new Student();でしょうか?
PerfectContrast

@PerfectContrast生徒、運転手、教師などをPersonとして持ち、それらをリストなどでグループ化する場合に便利です。したがって、「read」を呼び出すと、全員が独自の「read」メソッドを呼び出します。
サバンテ

205

継承とは、サブクラスでスーパークラスの構造と動作使用することを指します。

ポリモーフィズムとは、サブクラスのスーパークラスの動作変更することです。


5
この回答は、ポリモーフィズムには継承が必要であることを意味しますか?
jaco0646 2017

6
@ jaco0646-Javaのコンテキストでは、そう思います。(他の言語では、おそらくそれほど多くありません。)ここでは「スーパークラス」と「サブクラス」が大まかに使用されていることに注意してください。ポリモーフィズムは、インターフェースで指定された(ただし実装されていない)動作の継承も意味します。
テッドホップ2017

1
@AlirezaRahmani-コメントが理解できません。継承には、プロパティと動作の両方の継承が含まれないということですか?これは、Java(およびほとんどのクラスベースのオブジェクト指向言語)が継承を定義する方法とは逆です。Java言語仕様、§8.4.8:「AクラスCの継承その直接のスーパークラスからのすべての具体的な方法m(両方staticinstanceのスーパー...のは)」(相続についての詳細が続きます)。「コードの再利用」のように聞こえます。
Ted Hopp 2017年

@TedHopp Inheritanceは主にポリモーフィックツールですが、一部の人々は、後になって危険にさらされ、コードを再利用/共有する方法としてそれを使用しようとします。理論的根拠は「継承すればすべてのメソッドを無料で入手できる」ということですが、これら2つのクラスには多相関係がない可能性があるという事実を無視しています。
Alireza Rahmani Khalili 2017年

1
@AlirezaRahmani-Javaでは(タグによると、OPが具体的にこれについて尋ねたものです)、クラスの継承には最も確実に動作の継承が含まれます。それは言語定義の一部です。あなたが説明するようにこれが誤用される可能性があるという事実は、Javaの弱点の1つです。(関連する弱点は、クラスを宣言して、インターフェースで定義された定数をインポートするためだけにインターフェースを実装することでした。最終的に、Javaデザイナーimport staticは、インターフェースのこの誤用を排除するために導入されました。
Ted Hopp 2017年

63

ポリモーフィズム:異なるタイプのオブジェクトを同様に処理する機能。例:キリンとクロコダイルはどちらも動物であり、動物も可能Moveです。のインスタンスがある場合、AnimalそれがMoveどのタイプの動物であるかを知らず、気にせずに呼び出すことができます。

継承:これは、ポリモーフィズムとコードの再利用の両方を同時に実現する1つの方法です。

ポリモーフィズムの他の形式:ポリモーフィズムのみを提供し、コードの再利用は提供しないインターフェースなど、ポリモーフィズムを実現する他の方法があります(コードがまったく異なる場合がありMove、Snake などの場合とはかなり異なります)Move場合とDogの場合の場合があり、その場合、この場合は、インターフェースがポリモーフィックな選択として適しています。

他の動的言語では、ポリモーフィズムはDuck Typingで実現できます。これは、クラスが同じ基本クラスまたはインターフェイスを共有する必要さえなく、同じ名前のメソッドが必要なだけです。あるいは、Javascriptのようにさらに動的で、クラスもまったく必要ありません。同じメソッド名のオブジェクトだけを多態的に使用できます。


17

主な違いは、ポリモーフィズムは継承の特定の結果です。ポリモーフィズムは、呼び出されるメソッドが、オブジェクトのタイプに基づいて実行時に決定される場所です。これは、あるクラスが別のクラスを継承し、特定のメソッドをオーバーライドしているときに発生する状況です。ただし、通常の継承ツリーでは、メソッドをオーバーライドする必要はないため、すべてのメソッド呼び出しがポリモーフィックである必要はありません。それは理にかなっていますか?それはすべてのフォード車が自動車であるのと同様の問題ですが、すべての自動車がフォードであるわけではありません(かなりではありませんが...)。

さらに、継承はデータメンバーなども記述しますが、ポリモーフィズムはメソッドの呼び出しを扱います。


12

Javaでは、この2つは密接に関連しています。これは、Javaが「動的ディスパッチ」と呼ばれるメソッド呼び出しの手法を使用するためです。私が持っている場合

public class A {
  public void draw() { ... }
  public void spin() { ... }
}

public class B extends A {
  public void draw() { ... }
  public void bad() { ... }
}

...

A testObject = new B();

testObject.draw(); // calls B's draw, polymorphic
testObject.spin(); // calls A's spin, inherited by B
testObject.bad(); // compiler error, you are manipulating this as an A

次に、B spinがAから継承されていることがわかります。ただし、オブジェクトをタイプAであるかのように操作しようとすると、Bの動作が引き続き得られdrawます。draw動作は、多型です。

一部の言語では、ポリモーフィズムと継承はあまり密接に関連していません。たとえばC ++では、virtualと宣言されていない関数は継承されますが、動的にディスパッチされないため、継承を使用しても、その多態的な動作は得られません。

JavaScriptでは、すべての関数呼び出しが動的にディスパッチされ、弱い型付けが行われます。これは、それぞれが独自のdrawを持つ無関係なオブジェクトの束を持つことができ、それらに対して関数を反復して関数を呼び出すことができ、それぞれが正常に動作することを意味します。継承を必要とせずに、独自の多態性描画を使用できます。


12

多態性:ペンを販売する会社で働いているとします。したがって、ペンについて知る必要があるすべてのものを処理する「ペン」と呼ばれる非常に素晴らしいクラスを作成します。ペンクラスを使用して、請求、発送、請求書の作成など、あらゆる種類のクラスを記述します。ある日上司が来て、「素晴らしいニュースです。会社は成長しており、今はブックスとCDを販売しています!」ペンを使用するすべてのクラスをBook&CDも使用するように変更する必要があるため、良いニュースではありません。しかし、「SellableProduct」というインターフェースを最初に作成し、Penがこのインターフェースを実装した場合はどうなるでしょうか。次に、ペンの代わりにそのインターフェースを使用するために、すべての配送、請求などのクラスを作成することができます。あとは、SellableProductインターフェースを実装するBook&CompactDiscという新しいクラスを作成するだけです。ポリモーフィズムがあるため、他のすべてのクラスは変更なしで機能し続けることができます。意味をなす?

したがって、これは、多態性を実現する方法の1つである継承を使用することを意味します。

クラス/インターフェースでは多相性が発生する可能性がありますが、継承は常に2つ以上のクラス/インターフェース間で行われます。継承は常に「is-a」関係に準拠しますが、ポリモーフィズム(「is-a」/「has-a」関係の両方に準拠できる)とは常に一致しません。


6

継承はより静的なものであり(1つのクラスが別のクラスを拡張)、ポリモーフィズムは動的/実行時のものです(オブジェクトは静的/宣言型ではなく、動的/実行時型に従って動作します)。

例えば

// This assignment is possible because B extends A
A a = new B();
// polymorphic call/ access
a.foo();

-> aの静的/宣言型はAですが、実際の動的/実行時型はBなので、a.foo()はAではなくBで定義されているようにfooを実行します。


3

ポリモーフィズムは、類似した特性を持つオブジェクトのタイプ間の共通の動作を表現するアプローチです。また、これらの特性のバリエーションをオーバーライドによって作成することもできます。継承は、オブジェクトが関係と抽象的な動作を表すオブジェクト階層を通じてポリモーフィズムを実現する方法です。ただし、ポリモーフィズムを実現する方法はこれだけではありません。プロトタイプは、継承とは異なるポリモーフィズムを表現する別の方法です。JavaScriptは、プロトタイプを使用する言語の例です。他の方法もあると思います。


3

継承は、コードの再利用に関連する概念です。たとえば、私は、親クラスの発言権を持っている場合Animal、それは特定の属性とメソッド(この例で言うために含まれているmakeNoise()とするsleep())と私はと呼ばれる2つの子クラスを作成DogしてCat。犬と猫の両方が同じ方法でスリープ状態になるので(私は想定します)、親クラスによって提供されるおよびサブクラスのsleep()メソッドに機能を追加する必要はありません。ただし、DogCatAnimalDog吠え声と鳴き声がCatそうなので、Animalクラスは音を出すメソッドを持っているかもしれません、犬と猫はお互いにそして他の動物に比べて異なる音を出します。したがって、特定のタイプの動作を再定義する必要があります。したがって、ポリモーフィズムの定義。お役に立てれば。


3

Oracleのドキュメントでは、違いを正確に引用しています。

継承:クラスは、直接または間接にかかわらず、そのすべてのスーパークラスからフィールドとメソッドを継承しますサブクラスは、継承するメソッドをオーバーライドしたり、継承したフィールドやメソッドを非表示にしたりできます。(フィールドを非表示にすることは、一般にプログラミングの習慣としては好ましくないことに注意してください。)

ポリモーフィズム: ポリモーフィズムとは、生物や種が多くの異なる形態や段階を持つことができる生物学の原理を指します。この原則は、オブジェクト指向プログラミングやJava言語などの言語にも適用できます。クラスのサブクラスは、独自の動作を定義しながら、親クラスと同じ機能の一部を共有できます。

ポリモーフィズムはフィールドには適用されません。

関連記事:

ポリモーフィズムvsオーバーライドvsオーバーロード


1

ポリモーフィズム継承の影響です。これは、互いに拡張するクラスでのみ発生します。クラスの正確なタイプを知らなくても、クラスのメソッドを呼び出すことができます。また、ポリモーフィズムは実行時に発生します

たとえば、Javaポリモーフィズムの例:

ここに画像の説明を入力してください

継承により、派生クラスはそれらの基本クラスのインターフェースとコードを共有できます。コンパイル時に発生します

たとえば、Javaプラットフォームのすべてのクラスはオブジェクトの子孫です(画像提供:Oracle)。

ここに画像の説明を入力してください

Java継承Javaポリモーフィズムについてさらに学ぶために


0

継承は、クラスAがObjectまでのすべての親からすべての非静的な保護された/パブリックメソッド/フィールドを継承する場合です。


0

JAVAを使用する場合、次のように簡単です。

ポリモーフィズムは継承されたメソッドを使用していますが、それらを「オーバーライド」して何か別のことをしています(または、技術的にポリモーフィックではないので、superを呼び出した場合も同じです)。

私が間違っている場合は修正してください。


0

ポリモーフィズムの主な目的:スーパークラスへの参照変数を作成し、サブクラスオブジェクトを保持する=>オブジェクトは、複数の動作を実行できます

では、継承サブクラスはのプロパティを継承スーパークラスを


0

継承はポリモーフィズムの一種です。実際、継承は動的ポリモーフィズムです。そのため、継承を削除すると、オーバーライドできなくなります。


0

継承の実装は、スーパークラスで定義されている-ので、動作が継承されています。

class Animal
{
  double location;
  void move(double newLocation)
  {
    location = newLocation;
  }
}

class Dog extends Animal;

ポリモーフィズム実装はサブクラスで定義されている-これだけのインタフェースを継承しています。

interface Animal
{
  void move(double newLocation);
}

class Dog implements Animal
{
  double location;
  void move(double newLocation)
  {
    location = newLocation;
  }
}

0

ポリモーフィズムは、の継承によって実現されJavaます。

├── Animal
└── (instances)
    ├── Cat
    ├── Hamster
    ├── Lion
    └── Moose

├── interface-for-diet
   ├── Carnivore
   └── Herbivore
├── interface-for-habitat
   ├── Pet
   └── Wild

public class Animal {
    void breath() {
    };
}

public interface Carnivore {
    void loveMeat();
}

public interface Herbivore {
    void loveGreens();
}

public interface Pet {
    void liveInside();
}

public interface Wild {
    void liveOutside();
}

public class Hamster extends Animal implements Herbivore, Pet {

    @Override
    public void liveInside() {
        System.out.println("I live in a cage and my neighbor is a Gerbil");
    }

    @Override
    public void loveGreens() {
        System.out.println("I eat Carrots, Grapes, Tomatoes, and More");
    }
}

public class Cat extends Animal implements Carnivore, Pet {
    @Override
    public void liveInside() {
        System.out.println("I live in a cage and my neighbr is a Gerbil");
    }

    @Override
    public void loveMeat() {
        System.out.println("I eat Tuna, Chicken, and More");
    }
}

public class Moose extends Animal implements Herbivore, Wild {

    @Override
    public void liveOutside() {
        System.out.println("I live in the forest");
    }

    @Override
    public void loveGreens() {
        System.out.println("I eat grass");
    }
}

public class Lion extends Animal implements Carnivore, Wild {

    @Override
    public void liveOutside() {
        System.out.println("I live in the forest");
    }

    @Override
    public void loveMeat() {
        System.out.println("I eat Moose");
    }
}

Hamsterクラス継承構造からAnimalHerbivoreおよびPet展示するポリモーフィック行動主義国内のペットのを。

Catクラス継承構造からAnimalCarnivorePetも発揮するポリモーフィック行動主義国内のペットのを。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.