ポリモーフィズムとは何ですか、それは何のためにあり、どのように使用されますか?


564

ポリモーフィズムとは何ですか、それは何のためにあり、どのように使用されますか?


19
@ジョン:+1私はそれが最も興味深い現象であることに同意します。Unkwntechは、他の人がファンダメンタルズボキャブラリーと見なすものにギャップがある唯一の知識豊富で有能な個人ではないと確信しています。ちょうどプログラミングが非常に広い主題であることを示しに行きます。
AnthonyWJones 2009年

9
彼はそれを使うかもしれませんが、名前を付けないだけです。
エイデンベル

10
@Aamir:8kの誰かがプログラミングのすべての分野のすべてのファンダメンタルズを知っていると想定するのが妥当かどうかはわかりません。また、評判システムが不完全であることを示しているとは思いません。誰かは多くの良い質問をすることによってかなりの評判を得ることができます。この啓示に対する私たちの自然な反応は、私たち(プログラマー)が少し狭い心を持っているという自然な傾向(特定の技術分野で本当に優れている必要がある場合は悪いことではない)を示しているだけであり、それには欠点があります。
AnthonyWJones 2009年

43
あなたたちはプログラミングについて非常に限られた見方しか持っていないようです。OOの概念をまったく知らない(または必要としない)組み込み開発をしている人を知っています。彼らの概要は、コードからパフォーマンスのすべての最後のアトムを引き出すことであり、それだけです-彼らが取り組んでいるコードはオブジェクトの世界に入ることはありません。オブジェクト、ポリモーフィズム、2文字以上の変数名などの複雑な概念を学ぶ:-)
paxdiablo

29
どのようにて何かを学びますか?PHP OOPとデザインパターンを知っている人は誰もいなかったため、ある時点で、大学で学んだり、ここで答えたりなど、誰もがそれを学ばなければなりませんでした。 「そして、代わりに彼らがここでそれを学びたいと思っていることを考えてください。それがこのサイトの良い点でありポイントです。あなたが過去に助けられたと確信しいるので、あなたの時間を使って彼らを助けてください。代わりに、知識を共有する人間の歴史を通じて、応答が「!?ヘクタールあなたはそれを知らない何..」我々は、すべてのまだ暗いの年齢で...だろうだった場合
ジェームズ・

回答:


544

この用語のギリシャ語のルーツについて考えると、それが明らかになるはずです。

  • ポリ=多く:ポリゴン=多面、ポリスチレン=多くのスチレン(a)、ポリグロット=多くの言語など。
  • モーフ=変化または形態:形態=生物学的形態の研究、モルフェウス=あらゆる形態をとることができるギリシャの夢の神。

したがって、ポリモーフィズムとは、異なるプログラミング形式(データ型)に対して同じインターフェースを提示する(プログラミングにおける)機能です。

たとえば、多くの言語では、型が異なるという事実に関係なく、加算、減算、乗算などを行うことができるため、整数と浮動小数点は暗黙的にポリモーフィックです。通常の用語では、オブジェクトと見なされることはほとんどありません。

ただし、同じ方法で、BigDecimalor RationalまたはorのようなクラスImaginaryは、異なるデータ型を操作する場合でも、これらの操作を提供できます。

古典的な例は、Shapeクラスとそれから継承できるすべてのクラス(正方形、円、12面体、不規則な多角形、スプラットなど)です。

ポリモーフィズムでは、これらのクラスのそれぞれに異なる基礎データがあります。ポイント形状は2つの座標のみを必要とします(もちろん、2次元空間にあると仮定します)。円には中心と半径が必要です。正方形または長方形には、左上隅と右下隅の2つの座標と、(場合によっては)回転が必要です。不規則なポリゴンには一連の線が必要です。

クラスにそのコードとデータを処理させることにより、ポリモーフィズムを実現できます。この例では、すべてのクラスに独自のDraw()関数があり、クライアントコードは次のように簡単に実行できます。

shape.Draw()

任意の形状の正しい動作を取得します。

これは、コードは、データとは別にされた物事の古い方法とは対照的であり、そして次のような機能を持っているだろうdrawSquare()drawCircle()

オブジェクト指向、ポリモーフィズム、継承はすべて密接に関連した概念であり、それらを知ることは不可欠です。私の長いキャリアの間に多くの「銀の弾丸」がありましたが、基本的にはそれが消えてしまいましたが、OOパラダイムは良いものであることが判明しました。学ぶ、理解する、愛する-あなたがやったことを嬉しく思うでしょう:-)


(a)私はもともとそれを冗談として書いたが、それは正しいことが判明したため、それほどおかしくない。モノマーのスチレンはたまたま炭素と水素から作られ、ポリスチレンはそのグループから作られます。C8H8(C8H8)n

多分私はポリープが手紙の多くの出現であったと述べるべきだっpたのに、私は冗談を説明しなければならなかったが、それもおかしく見えない。

時々、あなたは後ろにいる間、ただやめるべきです:-)


50
ラテン語ではなくギリシャ語:)(「y」と「ph」はプレゼントです)。そしてギリシャ語では、「モーフ-」は単に「形状」または「フォーム」です。「モーフ」の「形状を変更する」の英語の意味は後の開発です
AakashM

16
ポリモーフィズムはOOPとは関係ありませんが、OOPは本質的にそれをサポートしているため(適切なOOP言語であると想定して)、ポリモーフィズムと関係があります。ポリモーフィズムの他の例については、FPを参照してください。
代替

9
これらの2行は私にとってトリックを行いました:Poly = many and Morph = change or form
Jo Smo

3
Polypはpolypo(u)sの略です。そしてポウはギリシャ語で足です。;-)
Dirk

2
@ショーン、「インターフェース」という言葉を文字通り/狭義の意味で使用しているのではないかと思います。これは、任意のコンピューター言語に固有の定義ではなく、英語の言葉として使用したものです。これは、まったく同じ関数をまったく同じパラメーターで意味するのではなく、単に、基礎となる具体的なタイプに関係なく、同じように「オブジェクト」に影響を与える方法です。これには、さまざまなパラメーターの型によるメソッドのオーバーロードや、より純粋な形の多態性が含まれる場合があります。
paxdiablo

250

ポリモーフィズムとは、オブジェクトを何かのジェネリックバージョンとして扱うことができる場合ですが、オブジェクトにアクセスすると、コードはオブジェクトの正確なタイプを判別し、関連するコードを呼び出します。

これはC#の例です。コンソールアプリケーション内に4つのクラスを作成します。

public abstract class Vehicle
{
    public abstract int Wheels;
}

public class Bicycle : Vehicle
{
    public override int Wheels()
    {
        return 2;
    }
}

public class Car : Vehicle
{
    public override int Wheels()
    {
        return 4;
    }
}

public class Truck : Vehicle
{
    public override int Wheels()
    {
        return 18;
    }
}

次に、コンソールアプリケーションのモジュールのMain()に以下を作成します。

public void Main()
{
    List<Vehicle> vehicles = new List<Vehicle>();

    vehicles.Add(new Bicycle());
    vehicles.Add(new Car());
    vehicles.Add(new Truck());

    foreach (Vehicle v in vehicles)
    {
        Console.WriteLine(
            string.Format("A {0} has {1} wheels.",
                v.GetType().Name, v.Wheels));
    }
}

この例では、ベースクラスVehicleのリストを作成します。これは、各サブクラスが持つホイールの数はわかりませんが、各サブクラスが持つホイールの数を知る責任があることは知っています。

次に、自転車、車、トラックをリストに追加します。

次に、リスト内の各Vehicleをループして、それらをすべて同じように扱うことができますが、各Vehicleの「Wheels」プロパティにアクセスすると、Vehicleクラスがそのコードの実行を関連するサブクラスに委譲します。

実行される正確なコードは実行時に参照されるサブクラスによって決定されるため、このコードはポリモーフィックであると言われています。

これがお役に立てば幸いです。


6
これは親インターフェースを明確に示すための非常に良い例だと思います。具体的なバージョンが必要になるのは、オブジェクトがインスタンス化されるまでです。つまり、車両対自動車
有線00 '10 / 10/30

1
これが最も明確な例だと思いますが、PHPプログラマーであれば、このリンクを最初に確認してから、後でこのリンクを確認する方が簡単かもしれません。code.tutsplus.com
Oliver Williams

また、(OPの範囲を超えて)分析を既知のオブジェクトに制限していることに注意してください。オブジェクト(インポートファイルなど)を渡さずに、オブジェクトの種類(Excel、CSV、YAML、SQLなど)を決定するのではありません。以下のためのファクトリクラスのいくつかの並べ替えが必要になります。このいずれかの操作を行いClass_ExcelClass_CSV呼ばれるように、または持っているReaderというクラスを。いずれにせよ、if / then / elseをどこかに保存する必要がある場合、ある種の反復処理が必要になります。
Oliver Williams

@Antony Gibbs:これは私にとって意味のある本当に良い例(ジェネリック型のリスト)です。そうでなければ、各クラスに基本クラスから継承せずに独自のホイール機能を持​​たせることの大きな意味は何ですか?リストの他に、ポリモーフィックに適した概念は他にありますか?
TTT 2018年

195

PHPでのポリモーフィズムの理解と適用から、Steve Guidettiに感謝します。

ポリモーフィズムは、非常に単純な概念の長い言葉です。

ポリモーフィズムは、共通のインターフェイスを共有しながらクラスが異なる機能を持つオブジェクト指向プログラミングのパターンを表します。

ポリモーフィズムの優れた点は、さまざまなクラスを使用するコードは、どのクラスも同じように使用されるため、どのクラスを使用しているかを知る必要がないことです。ポリモーフィズムの実例はボタンです。ボタンの使い方は誰もが知っています。ボタンを押すだけです。ただし、ボタンの「機能」は、ボタンが何に接続されているか、およびボタンが使用されるコンテキストによって異なりますが、結果はボタンの使用方法には影響しません。上司からボタンを押すように指示された場合は、タスクを実行するために必要なすべての情報をすでに持っています。

プログラミングの世界では、ポリモーフィズムを使用して、アプリケーションをよりモジュール化して拡張可能にします。さまざまなアクションのコースを説明する厄介な条件ステートメントの代わりに、ニーズに基づいて選択する交換可能なオブジェクトを作成します。それがポリモーフィズムの基本的な目標です。


10
ボタンの類推は抽象化の概念により関連しているのではないですか?
thewpfguy 2013年

6
オリジナルソース:code.tutsplus.com/tutorials/...
誰か

8
@Mantriur:これは確かに盗用され、そして我々はそれに対してルールを持っている:stackoverflow.com/help/referencingそれを削除する場合しかし、今のスコアを与え、古い記事は答えの削除の担当者の損失を免除されているという事実、私はわかりません今、完全に何でも改善します。次善の策は、ユーザーが自分の回答でソースを引用する責任があると私が強く信じているにもかかわらず、ユーザーに代わって属性を編集することです。
BoltClock

1
ポリモーフィズムがクラスやオブジェクト指向プログラミングに固有であることを暗示するのは間違っていると私は思います。アドホックなポリモーフィズムやパラメトリックポリモーフィズムが必ずしもクラスやオブジェクトを必要としないわけです。私はこの答えが話していることはサブタイピング(サブタイプ多型または包含多型としても知られている)だと思います。
StubbornShowaGuy

64

もし誰かがこれらの人々にCUTを言ったら

  1. 外科医
  2. ヘアスタイリスト
  3. 俳優

何が起こるか?

  • 外科医は切開を始めます。
  • ヘアスタイリストは誰かの髪をカットし始めます。
  • アクターは現在のシーンの外で演技を突然停止し、監督の指導を待ちました。

したがって、上記の表現は、OOPにおけるポリモーフィズム(同じ名前、異なる動作)とは何かを示しています。

面接に行くときに、面接官から、私たちが座っているのと同じ部屋で、多型のライブ例を教えて/見せてほしいと言われたら、

回答-ドア/窓

どのように疑問に思いますか?

ドア/窓を通して-人が来ることができる、空気が来ることができる、光が来ることができる、雨が来ることができる、など。

それをよりよく理解するために、私は上記の例を使用しました。コードの参照が必要な場合は、上記の回答に従ってください。


5
経験の浅い人が2つのクラスに.foo()メソッドがある場合、共通のインターフェースを共有する必要があると考える可能性があるため、これは良い例ではないと思います。ただし、これは真実ではなく、誤った抽象化につながります。インターフェースは、実行される役割を定義する必要があります。これには多くの異なる実装がある場合がありますが、すべて同じ入力のセットからプルし、同じ出力のセットから何かを返します。x.cut(...)外科医、スタイリスト、俳優のへの入力は同じではなく、どちらも出力ではありません。
Matt Klein

37

類推による簡単な説明

アメリカ合衆国大統領は多態性を採用しています。どうやって?まあ、彼は多くのアドバイザーを持っています:

  1. 軍事顧問
  2. 法律顧問
  3. 核物理学者(顧問として)
  4. 医療アドバイザー
  5. などなど

全員が1つのことに責任を負うべきです:例:

大統領は亜鉛コーティングや量子物理学の専門家ではありません。彼は多くのことを知っていませんが、知っていることは1つだけです。国の運営方法です。

それはコードと少し同じです:懸念と責任は関連するクラス/人々に分けられるべきです。そうでなければ、あなたは大統領に文字通り世界のすべてを知っているでしょう-ウィキペディア全体。ウィキペディア全体をコードのクラスに含めることを想像してください。維持するのは悪夢です。

大統領がこれらすべての特定のことを知るのはなぜ悪い考えなのでしょうか。

大統領が具体的に何をすべきかを伝えるとしたら、それは大統領が何をすべきかを正確に知る必要があることを意味します。大統領が特定のことを自分で知る必要がある場合、つまり、変更を加える必要がある場合は、1か所ではなく2か所で行う必要があります。

たとえば、EPAが汚染法を変更した場合、それが発生すると、EPAクラス大統領クラス変更する必要があります。1箇所ではなく2箇所でコードを変更するのは危険な場合があります。保守がはるかに難しいためです。

より良いアプローチはありますか?

より良いアプローチがあります:大統領は何かの詳細を知る必要はありません-彼はそれらのことをするために特に任命された人々から最高のアドバイスを要求することができます。

彼は国を運営するために多態的なアプローチを使うことができます。

例-多態的なアプローチの使用:

大統領がすることはすべて、人々に彼に助言するように頼むことです-そしてそれは実際に彼が実際に行うことです-そしてそれは良い大統領がすべきことです。彼の顧問はすべて異なった反応をしますが、彼らは皆、大統領が何を意味するかを知っています:Advise()。彼のオフィスには何百人もの人々がストリーミングしています。実際に彼らが誰であるかは問題ではありません。大統領が知っているのは、彼に彼らに「助言する」ように頼むとき、彼らはそれに応じてどのように対応するかを知っているということです。

public class MisterPresident
{
    public void RunTheCountry()
    {
        // assume the Petraeus and Condi classes etc are instantiated.
        petraeus.Advise(); // # Petraeus says send 100,000 troops to Fallujah
        condolezza.Advise(); // # she says negotiate trade deal with Iran
        healthOfficials.Advise(); // # they say we need to spend $50 billion on ObamaCare
    }
}

このアプローチにより、大統領は軍事的な事柄、ヘルスケア、国際外交について何も知らずに文字通り国を運営することができます。詳細は専門家に任されています。大統領が知っておくべき唯一のことは、「Advise()」です。

望まないこと:

public class MisterPresident
{
    public void RunTheCountry()
    {
        // people walk into the Presidents office and he tells them what to do
        // depending on who they are.

        // Fallujah Advice - Mr Prez tells his military exactly what to do.
        petraeus.IncreaseTroopNumbers();
        petraeus.ImproveSecurity();
        petraeus.PayContractors();

        // Condi diplomacy advice - Prez tells Condi how to negotiate

        condi.StallNegotiations();
        condi.LowBallFigure();
        condi.FireDemocraticallyElectedIraqiLeaderBecauseIDontLikeHim();

        // Health care

        healthOfficial.IncreasePremiums();
        healthOfficial.AddPreexistingConditions();
    }
}

番号!番号!番号!上記のシナリオでは、大統領はすべての作業を行っています。彼は部隊の数の増加と既存の状況について知っています。これは、中東の政策が変化した場合、大統領はペトレウス階級だけでなく、彼の命令も変更しなければならないことを意味します。大統領がそのような細部に行き詰まる必要はないはずなので、ペトラエウスのクラスを変更するだけでよい。彼は詳細について知る必要はありません。彼が知る必要があるのは、彼が1つの注文をした場合、すべてが面倒を見るということです。詳細はすべて専門家に委ねるべきです。

これにより、大統領は自分の最善を尽くすことができます。一般的なポリシーを設定し、見栄えをよくして、ゴルフをする:P。

それは実際にどのように実装されていますか-基本クラスまたは共通インターフェースを介して

要するに、これは多態性です。どのように正確に行われますか?「共通インターフェースの実装」を通じて、または基本クラス(継承)を使用して、これをより明確に説明する上記の回答を参照してください。(この概念をより明確に理解するには、インターフェースとは何かを理解する必要があり、継承とは何かを理解する必要があります。それがなければ、苦労するかもしれません。)

言い換えると、Petraeus、Condi、HealthOfficialsはすべて「インターフェースを実装する」クラスになります-それをIAdvisor1つのメソッドだけを含むインターフェースと呼びましょうAdvise()。しかし、今は詳細に入る。

これは理想的です

    public class MisterPresident
    {
            // You can pass in any advisor: Condi, HealthOfficials,
            //  Petraeus etc. The president has no idea who it will 
            // be. But he does know that he can ask them to "advise" 
            // and that's all Mr Prez cares for.

        public void RunTheCountry(IAdvisor governmentOfficer)
        {             
            governmentOfficer.Advise();              
        }
    }


    public class USA
    {
        MisterPresident president;

        public USA(MisterPresident president)
        {
            this.president = president;
        }

        public void ImplementPolicy()
        {
            IAdvisor governmentOfficer = getAdvisor(); // Returns an advisor: could be condi, or petraus etc.
            president.RunTheCountry(governmentOfficer);
        }
    }

概要

あなたが本当に知る必要があるすべてはこれです:

  • 大統領は詳細を知る必要はありません-それらは他人に任されています。
  • 大統領が知る必要があるのは、ドアを歩く人に助言を求めることだけです。そして、彼らが助言を求められたときに何をすべきかを彼らが絶対に知っていることを知っています(彼らはすべて実際にはアドバイザー(またはIAdvisor :)だからです)。

お役に立てれば幸いです。何もわからない場合はコメントを投稿してください。もう一度やります。


4
素晴らしい例!ありがとう。
Iman Sedighi 2017年

1
非常に興味深いアナロジー。ありがとうございました。
thanhtang 2017

1
@TTTは、(1)新しいアドバイザーが増えるたびに社長クラスを変更する必要があるためです。x2を変更したくないからです。一つだけです。(2)次に、既存のアドバイザーを変更する必要がある場合は、戻って社長クラスのこれら3つの呼び出しの1つを変更する必要がある場合があります。あなたは3回の別々の呼び出しがあった場合(3)その後、社長クラス内、依頼する必要があります。if healthAdvisor? then do this:そしてif petraus then do that etc.、このパターンが繰り返される必要があります、それはに、不要なと複雑です。上記の編集を参照してください。
BKSpurgeon

1
@TTTはい、あなたは正しいです。しかし、私は読者にゆっくりとコンセプトを紹介しなければなりません。さもなければ、彼らは理解しません。さらに変更を加えました。説明が必要な場合はアドバイスしてください
BKSpurgeon 2018年

1
@TTT基本クラスvsインターフェースは、プログラマーが多態性を実行するときに行う必要のある設計上の決定です。詳細については、こちらをご覧ください:stackoverflow.com/questions/56867/interface-vs-base-class
BKSpurgeon

24

ポリモーフィズムとは、オブジェクトのクラスを親クラスであるかのように扱う機能です。

たとえば、Animalというクラスと、Animalを継承するDogというクラスがあるとします。ポリモーフィズムは、次のように任意のDogオブジェクトをAnimalオブジェクトとして扱う機能です。

Dog* dog = new Dog;
Animal* animal = dog;

これは、@ Ajay Patelの(人気のある)説明とどのように関連しているのでしょうかclasses have different functionality while sharing a common interface
BornToCode

1
@BornToCode親クラスは、その共通インターフェースです/提供します。
grokmann、2014

1
ポリモーフィズムはサブタイプを必要としません。
Shaun Luttin 2017年

22

ポリモーフィズム:

これはオブジェクト指向プログラミングの概念です。異なるオブジェクトがそれぞれ独自の方法で同一のメッセージに応答する能力は、ポリモーフィズムと呼ばれます。

ポリモーフィズムは、すべてのクラスが独自の名前空間に存在するという事実から生じます。クラス定義内で割り当てられた名前は、その外部で割り当てられた名前と競合しません。これは、オブジェクトのデータ構造のインスタンス変数とオブジェクトのメソッドの両方に当てはまります。

  • C構造体のフィールドが保護された名前空間にあるように、オブジェクトのインスタンス変数もそうです。

  • メソッド名も保護されています。C関数の名前とは異なり、メソッド名はグローバルシンボルではありません。1つのクラスのメソッドの名前は、他のクラスのメソッド名と競合することはできません。2つのまったく異なるクラスが、同じ名前のメソッドを実装できます。

メソッド名はオブジェクトのインターフェースの一部です。オブジェクトが何かをするように要求するメッセージが送信されると、メッセージはオブジェクトが実行するメソッドを指定します。異なるオブジェクトは同じ名前のメソッドを持つことができるため、メッセージの意味は、メッセージを受信する特定のオブジェクトに関連して理解する必要があります。2つの異なるオブジェクトに同じメッセージを送信すると、2つの異なるメソッドを呼び出すことができます。

ポリモーフィズムの主な利点は、プログラミングインターフェースが簡素化されることです。クラスごとにクラスで再利用できる規則を確立できます。プログラムに追加する新しい関数ごとに新しい名前を作成する代わりに、同じ名前を再利用できます。プログラミングインターフェイスは、それらを実装するクラスとは別に、一連の抽象的な動作として説明できます。

例:

例1:Python 2.xで記述された簡単な例を次に示します。

class Animal:
    def __init__(self, name):    # Constructor of the class
        self.name = name
    def talk(self):              # Abstract method, defined by convention only
        raise NotImplementedError("Subclass must implement abstract method")

class Cat(Animal):
    def talk(self):
        return 'Meow!'

class Dog(Animal):
    def talk(self):
        return 'Woof! Woof!'

animals = [Cat('Missy'),
           Dog('Lassie')]

for animal in animals:
    print animal.name + ': ' + animal.talk()

例2:ポリモーフィズムは、メソッドのオーバーロードとメソッドのオーバーライドの概念を使用してJavaで実装されます

ポリモーフィズムを議論するための車の例を考えてみましょう。フォード、ホンダ、トヨタ、BMW、ベンツなどのあらゆるブランドを取りましょう。すべてがタイプの車です。

しかし、それぞれに独自の高度な機能と、より高度なテクノロジーがあり、移動動作に関与しています。

次に、基本タイプのCarを作成します

Car.java

public class Car {

    int price;
    String name;
    String color;

    public void move(){
    System.out.println("Basic Car move");
    }

}

フォードカーの例を実装してみましょう。

FordはCar型を拡張して、そのすべてのメンバー(プロパティとメソッド)を継承します。

Ford.java

public class Ford extends Car{
  public void move(){
    System.out.println("Moving with V engine");
  }
}

上記のFordクラスはCarクラスを拡張し、move()メソッドも実装します。moveメソッドはInheritanceを通じてFordですでに使用可能ですが、Fordは独自の方法でメソッドを実装しています。これはメソッドのオーバーライドと呼ばれます。

Honda.java

public class Honda extends Car{
  public void move(){
    System.out.println("Move with i-VTEC engine");
  }
}

ちょうどフォードのよ​​うに、ホンダも車のタイプを拡張し、独自の方法で移動メソッドを実装しました。

メソッドのオーバーライドは、ポリモーフィズムを有効にするための重要な機能です。メソッドのオーバーライドを使用すると、サブタイプは、継承を通じて利用できるメソッドの動作方法を変更できます。

PolymorphismExample.java

public class PolymorphismExample {
  public static void main(String[] args) {
    Car car = new Car();
    Car f = new Ford();
    Car h = new Honda();

    car.move();
    f.move();
    h.move();

  }
}

ポリモーフィズムの出力例:

PolymorphismExampleクラスのメインメソッドで、Car、Ford、Hondaの3つのオブジェクトを作成しました。3つのオブジェクトはすべて、Carタイプで参照されます。

ここで重要な点に注意してください。スーパークラスタイプはオブジェクトのサブクラスタイプを参照できますが、その逆は不可能です。その理由は、継承を使用してスーパークラスのすべてのメンバーがサブクラスで利用可能であり、コンパイル時に、使用している参照型にアクセスしようとしているメソッドがあるかどうかをコンパイラが評価しようとするためです。

したがって、PolymorphismExampleの参照car、fおよびhの場合、moveメソッドはCarタイプから存在します。したがって、コンパイラは問題なくコンパイルプロセスをパスします。

しかし、ランタイム実行に関しては、仮想マシンはサブタイプであるオブジェクトのメソッドを呼び出します。したがって、メソッドmove()はそれぞれの実装から呼び出されます。

したがって、すべてのオブジェクトはCarタイプですが、実行時の実行は、呼び出しが発生するオブジェクトに依存します。これはポリモーフィズムと呼ばれます。


オーバーロードの概念は、継承とポリモーフィズムとは関係ありません。
srk 2017年

@srkメソッドのオーバーロードは、ポリモーフィズムを実装する1つの方法です。多くの場合、静的またはアドホックなポリモーフィズムとして分類されます。wiki.c2.com/?CategoryPolymorphism
Shaun Luttin 2017年

12

通常、これはタイプAのオブジェクトがタイプBのオブジェクトのように動作する機能を指します。オブジェクト指向プログラミングでは、これは通常、継承によって実現されます。続きを読むためのウィキペディアのリンク:

編集:壊れたリンクを修正しました。


10
「タイプAのオブジェクトがタイプBのオブジェクトのように動作する能力」-これは正確な定義ではありません。私はそれがより多くのそれはタイプBのオブジェクトのようにタイプAの対象を治療する能力のようなものだと言うだろう
アルテムバーガー

はい。多分それはより良い言い回しです。
JesperE 2009年

完全を期すために、Pythonなどの多くの言語では、ダックタイピングを通じて多態性を実装しています。
ilya n。

私はこの@Ajayパテルが与えた(人気の)説明に関連しているか疑問に思うclasses have different functionality while sharing a common interface
BornToCode

9

ポリモーフィズムはこれです:

class Cup {
   int capacity
}

class TeaCup : Cup {
   string flavour
}

class CoffeeCup : Cup {
   string brand
}

Cup c = new CoffeeCup();

public int measure(Cup c) {
    return c.capacity
}

特定のインスタンスの代わりにカップだけを渡すことができます。各カップタイプごとに特定のmeasure()インスタンスを提供する必要がないため、これは一般的に役立ちます。


2
これは特にサブタイプの多型です。
Shaun Luttin 2017年

@ vinko-vrsalovic:田舎のアメリカのソフトウェア開発はどうですか?
TTT 2018年

8

私はこれが良い答えの多い古い質問であることを知っていますが、1文の回答を含めたいです。

派生型を基本型であるかのように扱う。

上記の例はたくさんありますが、これは簡潔な答えだと思います。


2
これはサブタイプ化であり、ポリモーフィズムの1種類にすぎません。
Shaun Luttin 2017年

@ShaunLuttinは、他のタイプのポリモーフィズムについて詳しく学ぶためのリソースを教えてもらえますか?
安倍ミースラー2017年

「サブタイプポリモーフィズム」に加えて、「アドホックポリモーフィズム」と「パラメータポリモーフィズム」があります。
Shaun Luttin 2017年

8

(私はまったく異なる何かについて別の記事を閲覧していました。そして、ポリモーフィズムがポップアップしました...今、私はポリモーフィズムが何であるかを知っていたと思いましたが...まだそれを共有します...)

http://www.eioba.com/a/1htn/how-i-explained-rest-to-my-wife

この部分から読んでください:

.....ポリモーフィズム。これは、さまざまな名詞に同じ動詞を適用できるという、マニアックな言い方です。


5

一般的に言えば、同じまたは表面的に類似したAPIを使用して、多数の異なるタイプのオブジェクトをインターフェースする機能です。さまざまな形式があります。

  • 関数のオーバーロード:sqrt(float)、sqrt(double)、sqrt(complex)など、同じ名前と異なるパラメーター型を持つ複数の関数を定義します。これを許可するほとんどの言語では、コンパイラーは渡される引数のタイプに応じて正しいものを自動的に選択するため、これはコンパイル時のポリモーフィズムです。

  • OOPの仮想メソッド:クラスのメソッドは、そのサブクラスの詳細に合わせて調整されたさまざまな実装を持つことができます。これらはそれぞれ、基本クラスで指定された実装をオーバーライドすると言われています。基本クラスまたはそのサブクラスのオブジェクトである可能性がある場合、正しい実装がその場で選択されるため、これは実行時のポリモーフィズムです。

  • テンプレート:一部のオブジェクト指向言語の機能で、関数、クラスなどを型でパラメーター化できます。たとえば、一般的な「リスト」テンプレートクラスを定義し、「整数のリスト」、「文字列のリスト」、「文字列のリストのリスト」などとしてインスタンス化できます。通常、任意の要素タイプのデータ構造に対してコードを1回記述し、コンパイラーはさまざまな要素タイプに対してそのバージョンを生成します。


4

ポリモーフィズムという用語の由来は次のとおりです。

ポリ=多く

モーフィズム=変化する能力

プログラミングでは、ポリモーフィズムは、オブジェクトを複数のタイプのものとして「見る」ことができる「技術」です。例えば:

生徒オブジェクトは人物オブジェクトでもあります。学生を「見る」(つまりキャストする)場合は、おそらく学生IDを要求できます。あなたはいつも人とそれをすることはできませんよね?(人は必ずしも学生ではないため、学生IDがない場合があります)。しかし、人はおそらく名前を持っています。学生もそうです。

結論として、異なる「角度」から同じオブジェクトを「見る」と、異なる「視点」(つまり、異なるプロパティまたはメソッド)が得られます。

したがって、この手法では、さまざまな角度から「見る」ことができるものを構築できます。

なぜポリモーフィズムを使用するのですか?手始めに…抽象化。この時点でそれは十分な情報であるはずです:)


3

類推を使ってみましょう。与えられた音楽台本に対して、それを演奏するすべてのミュージシャンは、解釈に彼女自身のタッチを与えます。

ミュージシャンはインターフェイスで抽象化できます。ミュージシャンが属するジャンルは、解釈のグローバルルールを定義する抽象クラスにすることができ、演奏するすべてのミュージシャンは具象クラスでモデル化できます。

あなたが音楽作品のリスナーである場合、スクリプトへの参照があります。たとえば、バッハの「フーガとトカタ」であり、それを実行するすべてのミュージシャンは独自の方法で多態性を示します。

これは、可能な設計の例(Javaの場合)です。

public interface Musician {
  public void play(Work work);
}

public interface Work {
  public String getScript();
}

public class FugaAndToccata implements Work {
  public String getScript() {
    return Bach.getFugaAndToccataScript();
  }
}

public class AnnHalloway implements Musician {
  public void play(Work work) {
    // plays in her own style, strict, disciplined
    String script = work.getScript()
  }
}

public class VictorBorga implements Musician {
  public void play(Work work) {
    // goofing while playing with superb style
    String script = work.getScript()
  }
}

public class Listener {
  public void main(String[] args) {
    Musician musician;
    if (args!=null && args.length > 0 && args[0].equals("C")) {
      musician = new AnnHalloway();
    } else {
      musician = new TerryGilliam();
    }
    musician.play(new FugaAndToccata());
}

1
AnnHallowayそしてVictorBorga、それらはクラスではなくオブジェクトであるべきだと感じます-あなたの例は、例えば、public class Pianist implements Musicianそして、victorBorge = new Pianist();など
Przemek D

3

別の質問のために、ポリモーフィズムの概要を提供しました。

C ++でのポリモーフィズム

それが役に立てば幸い。抽出...

...簡単なテストと[ポリモーフィズム]の定義から始めるのに役立ちます。コードを考えてみましょう:

Type1 x;
Type2 y;

f(x);
f(y);

ここでf()は、いくつかの操作を実行し、値xy入力が与えられています。ポリモーフィックであるためにf()は、少なくとも2つの異なる型(例:intdouble)の値を操作して、型に適したコードを見つけて実行できる必要があります。

C ++のポリモーフィズムに続く)


3

ポリモーフィズムは、さまざまな形でとることができるオブジェクトの能力です。たとえば、人間のクラスでは、人間は人間関係について話すときにさまざまな形で行動することができます。例:男は息子の父親であり、夫は妻の夫であり、生徒の教師です。


3

ポリモーフィズムは、オブジェクトがさまざまな形をとる能力です。OOPでのポリモーフィズムの最も一般的な使用法は、親クラス参照を使用して子クラスオブジェクトを参照する場合に発生します。Javaで作成されたこの例では、3つのタイプの車両があります。3つの異なるオブジェクトを作成し、wheelsメソッドを実行してみます。

public class PolymorphismExample {

    public static abstract class Vehicle
    {
        public int wheels(){
            return 0;
        }
    }

    public static class Bike extends Vehicle
    {
        @Override
        public int wheels()
        {
            return 2;
        }
    }

    public static class Car extends Vehicle
    {
        @Override
        public int wheels()
        {
            return 4;
        }
    }

    public static class Truck extends Vehicle
    {
        @Override
        public int wheels()
        {
            return 18;
        }
    }

    public static void main(String[] args)
    {
        Vehicle bike = new Bike();
        Vehicle car = new Car();
        Vehicle truck = new Truck();

        System.out.println("Bike has "+bike.wheels()+" wheels");
        System.out.println("Car has "+car.wheels()+" wheels");
        System.out.println("Truck has "+truck.wheels()+" wheels");
    }

}

結果は次のとおりです。

結果

詳細については、https://github.com/m-vahidalizadeh/java_advanced/blob/master/src/files/PolymorphismExample.javaにアクセスしてください。お役に立てば幸いです。


はい、しかし、あなたは多態性の利点が何であるかを説明しませんでした。Vehicleクラスを削除するより短いコードが明らかにあり、それは(もちろん、異なるオブジェクト宣言で)機能します。
Cornelius

質問した人は利点について質問しなかったので、私は説明しませんでした。彼は尋ねました:「多型とは何ですか、それは何のために、そしてどのように使用されますか?」コードについて、もっとうまくできる場合は、回答を投稿してください。したがって、私たちのコミュニティはそれを使用できます。ご意見ありがとうございます。
Mohammad

失礼な言い方をしたくありませんでした。他の人も説明しませんでした。少なくとも、コードを入力するのは面倒だった。とにかく、彼はそれが何のためにあるのか尋ねましたが、このページの例のどれもそれが何のためにあるのかを説明していません。あなたは皆、これと同じ結果を得る複雑な方法を提示しています:s28.postimg.org/jq8vl6031/Poly.jpgそして、ポリモーフィズムを使用したい理由、その利得または目的、何ができなかったのかを説明する人は誰もいませんでしたそれが使用されなかった場合に行われましたか?私はこのページでご覧すべては階段を使ってあなたのアパートに登るための提案ではなく、エレベーター..です
コーネリアス

..エレベーターに合わせるには大きすぎる旗竿を持っていることに気づかずに。コードを投稿する方法がわからないので、あまり役に立ちません...
Cornelius

2

ポリモーフィズムとは、オブジェクトのニーズに応じて、オブジェクトの種類ごとに異なる処理を実行する同じ名前のメソッドをプログラマが作成する機能です。たとえば、と呼ばれるクラスとFractionと呼ばれるクラスを開発している場合ComplexNumber、どちらにもと呼ばれるメソッドが含まれている可能性がありますdisplay()が、それぞれが異なる方法でそのメソッドを実装します。たとえば、PHPでは、次のように実装します。

//  Class definitions

class Fraction
{
    public $numerator;
    public $denominator;

    public function __construct($n, $d)
    {
        //  In real life, you'd do some type checking, making sure $d != 0, etc.
        $this->numerator = $n;
        $this->denominator = $d;
    }

    public function display()
    {
        echo $this->numerator . '/' . $this->denominator;
    }
}

class ComplexNumber
{
    public $real;
    public $imaginary;

    public function __construct($a, $b)
    {
        $this->real = $a;
        $this->imaginary = $b;
    }

    public function display()
    {
        echo $this->real . '+' . $this->imaginary . 'i';
    }
}


//  Main program

$fraction = new Fraction(1, 2);
$complex = new ComplexNumber(1, 2);

echo 'This is a fraction: '
$fraction->display();
echo "\n";

echo 'This is a complex number: '
$complex->display();
echo "\n";

出力:

This is a fraction: 1/2
This is a complex number: 1 + 2i

他の回答のいくつかは、ポリモーフィズムが継承と組み合わせてのみ使用されることを暗示しているようです。例えば、多分FractionComplexNumber呼ばれる抽象クラス実装の両方のNumber方法があるdisplay()両方の実施を義務付けている分数や複素数を、。しかし、あなたは必要ありません、ポリモーフィズムを利用するために継承。

少なくともPHPのような動的に型付けされた言語(C ++やJavaについては知りません)では、ポリモーフィズムにより、開発者は必ずしもオブジェクトの型を事前に知る必要がなく、メソッドの正しい実装が呼ばれる。たとえば、ユーザーがNumber作成されたタイプを選択するとします。

$userNumberChoice = $_GET['userNumberChoice'];

switch ($userNumberChoice) {
    case 'fraction':
        $userNumber = new Fraction(1, 2);
        break;
    case 'complex':
        $userNumber = new ComplexNumber(1, 2);
        break;
}

echo "The user's number is: ";
$userNumber->display();
echo "\n";

この場合、display()開発者がユーザーが分数と複素数のどちらを選択するかを事前に知ることができない場合でも、適切なメソッドが呼び出されます。


2
それは多態性ではありません。これは、同じ名前のメソッドを持つ2つのクラスです。それらは、「表示可能」または類似の基本クラスまたはインターフェースによってリンクされる必要があり、他のメソッドは、オブジェクトがComplexまたはFractionではなく「displayable」型であることを単に気にします。
ポッド

私は常に、ポリモーフィズム「同じノームのメソッドを持つ2つのクラス」だと思っていました。実際、Stephan Kochan(私がこのFraction / Complexの例を恥知らずに引き裂いている)を引用すると、「異なるクラス間で同じメソッド名を共有する機能は、ポリモーフィズムと呼ばれます」。(Programming_In_Objective-Cから)基本クラスを介してクラスをリンクする必要性については言及していません。多分それは異なる言語で異なるでしょう、正直に知りません。
Alex Basson

この定義が出版された本から引用されているのは難しいとしても、私はそれが正しくないと主張します。特にそれは他のすべてと衝突するように見えるので、多形性の言語にとらわれない定義。そして、最終的な結果はポリモーフィズムで見られるものと同じですが、プログラマーがメソッドの正しい実装が他の類似した名前のメソッドの中で呼び出されていることを推し進めることができるのは、動的タイピングであると私は主張します。
vipirtti 2009年

2

オブジェクト指向プログラミングでは、ポリモーフィズムとは、データ型やクラスに応じてオブジェクトを異なる方法で処理するプログラミング言語の能力を指します。具体的には、派生クラスのメソッドを再定義する機能です。


2

多態性は文字通り、複数の形状を意味します。(または多くの形式):異なるクラスおよび同じ名前のメソッドのオブジェクトですが、ワークフローは異なります。簡単な例は次のとおりです。

人Xについて考えます。

彼はたった一人ですが、彼は同じように行動します。あなたはどのように尋ねるかもしれません:

彼は母親の息子です。彼の友人への友人。兄から妹へ。


2

OOPでのポリモーフィズムとは、クラスが異なる型を持つ可能性があることを意味します。継承は、ポリモーフィズムを実装する1つの方法です。

たとえば、Shapeはインターフェイスであり、SquareCircleDiamondのサブタイプがあります。これでSquareオブジェクトができました。SquareはShapeなので、SquareをShapeに自動的にアップキャストできます。ただし、ShapeをSquareにダウンキャストする場合は、明示的な型キャストを行う必要があります。ShapeがSquareであるとは言えないため、Circleの場合もあります。したがってSquare s = (Square)shape、のようなコードを使用して手動でキャストする必要があります。形状がCircleの場合、java.lang.ClassCastExceptionCircleはSquareではないため、結果はになります。


2

ポリモーフィズム:

参照変数のタイプではなく、クラスのインスタンスによって異なる実行。

インターフェイス型参照変数は、そのインターフェイスを実装する任意のクラスインスタンスを参照できます。


1

ポリモーフィズムは、指定されたクラスでオブジェクトを使用する機能です。オブジェクトを構成するすべてのコンポーネントは、指定されたクラスのサブクラスによって継承されます。つまり、このオブジェクトがクラスによって宣言されると、そのオブジェクトの下のすべてのサブクラス(およびそのサブクラスなど)は、オブジェクトとそのコンポーネント(メイクアップ)を継承します。

各クラスは個別のファイルに保存する必要があることに注意してください。

次のコードは、ポリモーフィズムの例です。

スーパークラス:

public class Parent {
    //Define things that all classes share
    String maidenName;
    String familyTree;

    //Give the top class a default method
    public void speak(){
         System.out.println("We are all Parents");
    }
}

父親、サブクラス:

public class Father extends Parent{
    //Can use maidenName and familyTree here
    String name="Joe";
    String called="dad";

    //Give the top class a default method
    public void speak(){
        System.out.println("I am "+name+", the father.");
    }
}

子、別のサブクラス:

public class Child extends Father {
    //Can use maidenName, familyTree, called and name here

    //Give the top class a default method
    public void speak(){
        System.out.println("Hi "+called+". What are we going to do today?");
    }
}

実行メソッドは、開始するために親クラスを参照します。

public class Parenting{
    public static void main(String[] args) {
        Parent parents = new Parent();
        Parent parent = new Father();
        Parent child = new Child();

        parents.speak();
        parent.speak();
        child.speak();
    }
}

各クラスは個別の* .javaファイルで宣言する必要があることに注意してください。コードはコンパイルされるはずです。また、さらに下でmaidenNameとfamilyTreeを継続的に使用できることにも注意してください。それがポリモーフィズムの概念です。ここでは、継承の概念についても説明します。1つのクラスを使用するか、サブクラスでさらに定義します。

これが役立ち、明確になることを願っています。コードの検証に使用できるコンピューターが見つかったら、結果を投稿します。お待ちいただきありがとうございます。


2
すべての子供は親ではないので、この構造は間違っていることに注意してください。最上位クラスは子である必要があります(「Person」で始まるだけではない場合)。Adamを除いて常にtrueになります。Creatorは人間の知性の構成要素で定義できないため、彼のparent_idをnullに設定できます。
Yehosef 2014年

1

ポリモーフィズムは、同じルーチン(関数、メソッド)が異なる型に作用することを可能にします。

多くの既存の回答では、サブタイプとポリモーフィズムが混同されているため、ポリモーフィズムを実装する3つの方法(サブタイプを含む)を次に示します。

  • パラメータ化(ジェネリック)ポリモーフィズムを使用すると、ルーチンは通常のパラメータに加えて1つ以上のタイプパラメータを受け入れ、それらのタイプで実行することができます。
  • サブタイプ多型により、ルーチンはそのパラメーターの任意のサブタイプに作用することができます。
  • アドホックなポリモーフィズムは通常、ルーチンのオーバーロードを使用してポリモーフィックな動作を許可しますが、他のポリモーフィズム実装も参照できます。

以下も参照してください。

http://wiki.c2.com/?CategoryPolymorphism

https://en.wikipedia.org/wiki/Polymorphism_(computer_science)


0

オブジェクト指向言語では、ポリモーフィズムにより、同じインターフェースを介して異なるデータ型を処理および処理できます。たとえば、C ++の継承について考えてみます。クラスBはクラスAから派生しています。タイプA *のポインター(クラスAへのポインター)を使用して、クラスAのオブジェクトとクラスBのオブジェクトの両方を処理できます。


0

コーディング用語の多態性は、オブジェクトが継承などを通じて複数のタイプとして存在できる場合です。オブジェクトが持つ側面の数を定義する「Shape」という名前のクラスを作成すると、「Square」などのそれを継承する新しいクラスを作成できます。 」その後、「Square」のインスタンスを作成するときに、必要に応じて、「Shape」から「Square」に前後にキャストできます。


0

ポリモーフィズムは、あるモジュールを作成して別のモジュールを呼び出す機能を提供しますが、制御のフローではなく、制御のフローに対するコンパイル時の依存ポイントを持っています。

ポリモーフィズムを使用することにより、高レベルモジュールは低レベルモジュールに依存しません。どちらも抽象化に依存しています。これは、依存関係の逆転の原則を適用するのに役立ちます(https://en.wikipedia.org/wiki/Dependency_inversion_principle)。

これが私が上記の定義を見つけた場所です。ビデオの約50分前に、インストラクターが上記について説明します。 https://www.youtube.com/watch?v=TMuno5RZNeE


0

ポリモーフィズムとは何ですか?

ポリモーフィズムとは、次の機能です。

  • 特殊化された型のメソッドを呼び出すときに、その一般化された型を知っているだけで、特殊化された型のインスタンスで操作を呼び出します。これは、動的な多態性です。

  • 保存名はあるが異なるパラメーターを持ついくつかのメソッドを定義します。これは静的なポリモーフィズムです。

最初の場合は歴史的な定義と最も重要です。

ポリモーフィズムとは何ですか?

これにより、クラス階層の強く型付けされた一貫性を作成し、異なるタイプのオブジェクトのリストを、それらのタイプを知らずに親タイプの1つだけだけでなく、データバインディングとして管理するなど、いくつかの魔法のようことを行うことができます。

強いタイピングと弱いタイピング

サンプル

ポイント、ライン、四角形、円などのシェイプは、操作Draw()が何も受け取らないか、パラメータを消去してタイムアウトを設定します。

public class Shape
{
 public virtual void Draw()
 {
   DoNothing();
 }
 public virtual void Draw(int timeout)
 {
   DoNothing();
 }
}

public class Point : Shape
{
 int X, Y;
 public override void Draw()
 {
   DrawThePoint();
 }
}

public class Line : Point
{
 int Xend, Yend;
 public override Draw()
 {
   DrawTheLine();
 }
}

public class Rectangle : Line
{
 public override Draw()
 {
   DrawTheRectangle();
 }
}

var shapes = new List<Shape> { new Point(0,0), new Line(0,0,10,10), new rectangle(50,50,100,100) };

foreach ( var shape in shapes )
  shape.Draw();

ここで、ShapeクラスとShape.Draw()メソッドを抽象としてマークする必要があります。

彼らは理解するためのものではありません。

説明

ポリモーフィズムがなく、abstract-virtual-overrideを使用して、形状を解析しているとき、CLRが呼び出すメソッドがわからないため、呼び出されるのはSpahe.Draw()メソッドだけです。したがって、処理対象の型のメソッドを呼び出します。リスト宣言のため、ここでは型はShapeです。したがって、コードはまったく何もしません。

ポリモーフィズムを使用すると、CLRは、仮想テーブルと呼ばれるものを使用して、操作対象のオブジェクトの実際のタイプを推測できます。だからそれは良いメソッドメソッドを ShapeがPointの場合はShape.Draw()を呼び出して、Point.Draw()を呼び出します。したがって、コードは形状を描画します。

もっと読む

C#-ポリモーフィズム(レベル1)

Javaのポリモーフィズム(レベル2)

ポリモーフィズム(C#プログラミングガイド)

仮想メソッドテーブル

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