今日、モジュールの終わりに開かれた本の試験でこの質問が出され、私は迷っていました。私は読んでいてHead first Java
、両方の定義がまったく同じであるように見えました。自分の心の中での主な違いは何だろうと思っていました。これと同様の質問がいくつかあることは知っていますが、決定的な答えを提供するものはありません。
今日、モジュールの終わりに開かれた本の試験でこの質問が出され、私は迷っていました。私は読んでいてHead first Java
、両方の定義がまったく同じであるように見えました。自分の心の中での主な違いは何だろうと思っていました。これと同様の質問がいくつかあることは知っていますが、決定的な答えを提供するものはありません。
回答:
継承とは、「クラス」が既存の「クラス」から派生する場合です。したがって、Person
クラスがある場合Student
、拡張するクラスがありPerson
、そのすべてのものをStudent
継承しPerson
ます。Personのフィールド/メソッドに配置するアクセス修飾子の周りにいくつかの詳細がありますが、それは基本的な考え方です。たとえば、にプライベートフィールドがある場合Person
、Student
そのプライベートので、それを見ていない、とプライベートフィールドは、サブクラスには見えないだろう。
ポリモーフィズムは、プログラムの種類に応じて、使用するメソッドをプログラムがどのように決定するかを扱います。お持ちの場合はPerson
持っている、read
方法を、あなたは持ってStudent
延びているPerson
の独自の実装有している、read
あなたが持っている場合によっては、ランタイムがあなたのために決定されて呼び出されるメソッド、Person
またはStudent
。少しトリッキーになりますが、次のようなことをすると
Person p = new Student();
p.read();
Studentのreadメソッドが呼び出されます。それは実際の多型です。a Student
はである ため、この割り当てを行うことができますPerson
が、ランタイムはの実際のタイプp
がStudentであることを認識するのに十分スマートです。
詳細は言語によって異なります。たとえば、JavaScriptで継承を行うことができますが、Javaでの動作とはまったく異なります。
Person
のread
方法は、パブリックアクセス修飾子を使用しているが、しませんStudent
それらにアクセスできるようにオブジェクト?そして、それStudent s = new Student();
は簡単ではないでしょうか?私はまだ実際に多形主義の利点を実際にはあまり得ていません。
Person p = new Student();
代わりに使用したいのStudent p = new Student();
でしょうか?
継承とは、サブクラスでスーパークラスの構造と動作を使用することを指します。
ポリモーフィズムとは、サブクラスのスーパークラスの動作を変更することです。
m
(両方static
とinstance
のスーパー...のは)」(相続についての詳細が続きます)。「コードの再利用」のように聞こえます。
import static
は、インターフェースのこの誤用を排除するために導入されました。
ポリモーフィズム:異なるタイプのオブジェクトを同様に処理する機能。例:キリンとクロコダイルはどちらも動物であり、動物も可能Move
です。のインスタンスがある場合、Animal
それがMove
どのタイプの動物であるかを知らず、気にせずに呼び出すことができます。
継承:これは、ポリモーフィズムとコードの再利用の両方を同時に実現する1つの方法です。
ポリモーフィズムの他の形式:ポリモーフィズムのみを提供し、コードの再利用は提供しないインターフェースなど、ポリモーフィズムを実現する他の方法があります(コードがまったく異なる場合がありMove
、Snake などの場合とはかなり異なります)Move
場合とDogの場合の場合があり、その場合、この場合は、インターフェースがポリモーフィックな選択として適しています。
他の動的言語では、ポリモーフィズムはDuck Typingで実現できます。これは、クラスが同じ基本クラスまたはインターフェイスを共有する必要さえなく、同じ名前のメソッドが必要なだけです。あるいは、Javascriptのようにさらに動的で、クラスもまったく必要ありません。同じメソッド名のオブジェクトだけを多態的に使用できます。
主な違いは、ポリモーフィズムは継承の特定の結果です。ポリモーフィズムは、呼び出されるメソッドが、オブジェクトのタイプに基づいて実行時に決定される場所です。これは、あるクラスが別のクラスを継承し、特定のメソッドをオーバーライドしているときに発生する状況です。ただし、通常の継承ツリーでは、メソッドをオーバーライドする必要はないため、すべてのメソッド呼び出しがポリモーフィックである必要はありません。それは理にかなっていますか?それはすべてのフォード車が自動車であるのと同様の問題ですが、すべての自動車がフォードであるわけではありません(かなりではありませんが...)。
さらに、継承はデータメンバーなども記述しますが、ポリモーフィズムはメソッドの呼び出しを扱います。
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
を持つ無関係なオブジェクトの束を持つことができ、それらに対して関数を反復して関数を呼び出すことができ、それぞれが正常に動作することを意味します。継承を必要とせずに、独自の多態性描画を使用できます。
多態性:ペンを販売する会社で働いているとします。したがって、ペンについて知る必要があるすべてのものを処理する「ペン」と呼ばれる非常に素晴らしいクラスを作成します。ペンクラスを使用して、請求、発送、請求書の作成など、あらゆる種類のクラスを記述します。ある日上司が来て、「素晴らしいニュースです。会社は成長しており、今はブックスとCDを販売しています!」ペンを使用するすべてのクラスをBook&CDも使用するように変更する必要があるため、良いニュースではありません。しかし、「SellableProduct」というインターフェースを最初に作成し、Penがこのインターフェースを実装した場合はどうなるでしょうか。次に、ペンの代わりにそのインターフェースを使用するために、すべての配送、請求などのクラスを作成することができます。あとは、SellableProductインターフェースを実装するBook&CompactDiscという新しいクラスを作成するだけです。ポリモーフィズムがあるため、他のすべてのクラスは変更なしで機能し続けることができます。意味をなす?
したがって、これは、多態性を実現する方法の1つである継承を使用することを意味します。
クラス/インターフェースでは多相性が発生する可能性がありますが、継承は常に2つ以上のクラス/インターフェース間で行われます。継承は常に「is-a」関係に準拠しますが、ポリモーフィズム(「is-a」/「has-a」関係の両方に準拠できる)とは常に一致しません。
継承は、コードの再利用に関連する概念です。たとえば、私は、親クラスの発言権を持っている場合Animal
、それは特定の属性とメソッド(この例で言うために含まれているmakeNoise()
とするsleep()
)と私はと呼ばれる2つの子クラスを作成Dog
してCat
。犬と猫の両方が同じ方法でスリープ状態になるので(私は想定します)、親クラスによって提供されるおよびサブクラスのsleep()
メソッドに機能を追加する必要はありません。ただし、Dog
Cat
Animal
Dog
吠え声と鳴き声がCat
そうなので、Animal
クラスは音を出すメソッドを持っているかもしれません、犬と猫はお互いにそして他の動物に比べて異なる音を出します。したがって、特定のタイプの動作を再定義する必要があります。したがって、ポリモーフィズムの定義。お役に立てれば。
Oracleのドキュメントでは、違いを正確に引用しています。
継承:クラスは、直接または間接にかかわらず、そのすべてのスーパークラスからフィールドとメソッドを継承します。サブクラスは、継承するメソッドをオーバーライドしたり、継承したフィールドやメソッドを非表示にしたりできます。(フィールドを非表示にすることは、一般にプログラミングの習慣としては好ましくないことに注意してください。)
ポリモーフィズム: ポリモーフィズムとは、生物や種が多くの異なる形態や段階を持つことができる生物学の原理を指します。この原則は、オブジェクト指向プログラミングやJava言語などの言語にも適用できます。クラスのサブクラスは、独自の動作を定義しながら、親クラスと同じ機能の一部を共有できます。
ポリモーフィズムはフィールドには適用されません。
関連記事:
ポリモーフィズムは継承の影響です。これは、互いに拡張するクラスでのみ発生します。クラスの正確なタイプを知らなくても、クラスのメソッドを呼び出すことができます。また、ポリモーフィズムは実行時に発生します。
たとえば、Javaポリモーフィズムの例:
継承により、派生クラスはそれらの基本クラスのインターフェースとコードを共有できます。コンパイル時に発生します。
たとえば、Javaプラットフォームのすべてのクラスはオブジェクトの子孫です(画像提供:Oracle)。
Java継承とJavaポリモーフィズムについてさらに学ぶために
継承はポリモーフィズムの一種です。実際、継承は動的ポリモーフィズムです。そのため、継承を削除すると、オーバーライドできなくなります。
継承の実装は、スーパークラスで定義されている-ので、動作が継承されています。
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;
}
}
ポリモーフィズムは、の継承によって実現され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
クラス継承構造からAnimal
、Herbivore
およびPet
展示するポリモーフィック行動主義国内のペットのを。
Cat
クラス継承構造からAnimal
、Carnivore
とPet
も発揮するポリモーフィック行動主義国内のペットのを。