72

ポリモーフィズムの利点を探し始めたとき、ここでこの質問を見つけました。しかし、ここで私は自分の答えを見つけることができませんでした。私が見つけたいものを教えてください。ここにいくつかのクラスがあります:

class CoolingMachines{
    public void startMachine(){
        //No implementationion
    }
    public void stopMachine(){
        //No implementationion
    }
}

class Refrigerator extends CoolingMachines{
    public void startMachine(){
        System.out.println("Refrigerator Starts");
    }
    public void stopMachine(){
        System.out.println("Refrigerator Stop");
    }
    public void trip(){
        System.out.println("Refrigerator Trip");
    }
}

class AirConditioner extends CoolingMachines{
    public void startMachine(){
        System.out.println("AC Starts");
    }
    public void stopMachine(){
        System.out.println("AC Stop");
    }
}

public class PolymorphismDemo {
    CoolingMachines cm = new Refrigerator();
    Refrigerator rf = new Refrigerator();
}

ここで、Demo クラスに 2 つのオブジェクトを作成し、これらのオブジェクトを参照していRefrigeratorます。オブジェクトから のメソッドrfを呼び出すことができることを完全に理解しましたが、そのメソッドはオブジェクトに対して非表示になります。ここで私の質問は、なぜポリモーフィズムを使用する必要があるのか​​ 、またはなぜ使用する必要があるのか​​ ですtrip()Refrigeratorcm

CoolingMachines cm = new Refrigerator();

私が大丈夫なとき

Refrigerator rf = new Refrigerator();

ポリモーフィック オブジェクトの効率は良いですか、それとも軽量ですか? これらのオブジェクトの基本的な目的と違いは何ですか? と の間に違いはcm.start();ありrf.start()ますか?

4

9 に答える 9

73

リストを処理するときに便利です...短い例:

List<CoolingMachines> coolingMachines = ... // a list of CoolingMachines 
for (CoolingMachine current : coolingMachines) {
    current.start();
}

または、メソッドが任意のサブクラスで動作できるようにしたい場合CoolingMachines

于 2012-06-18T12:19:55.643 に答える
58

具体的なクラスを知っていても大丈夫な場合は、メリットはありません。ただし、多くの場合、基本クラスまたはインターフェイスについてのみ知っているコードを記述できるようにする必要があります。

たとえばIterablesGuavaを見てください。これは、どの実装が使用されているかを(ほとんど)気にしない多くのメソッドIterableです。実装ごとに個別にすべてのコードが本当に必要ですか?

抽象基本クラスまたはインターフェースにコーディングできる場合は、後で同じパブリックAPIを共有する他の実装を使用できるようにしますが、実装が異なる場合があります。単一の本番実装のみが必要な場合でも、テスト用の代替実装が必要になる場合があります。(これがどの程度適用されるかは、問題のクラスによって異なります。)

于 2012-06-18T12:18:39.183 に答える
31

AirConditioner後で冷却の代わりに使用したい場合Refrigerator、変更する必要があるのはコードだけですCoolingMachines cm = new AirConditioner();

于 2012-06-18T12:19:59.683 に答える
17

使いたい理由

CoolingMachines cm = new Refrigerator();

後で簡単に別のを使用できるということですCoolingMachines。その1行のコードを変更するだけで、残りのコードは引き続き機能します(のメソッドのみを使用するためCoolingMachines、などの特定のマシンよりも一般的ですRefrigerator)。

したがって、の特定のインスタンスのRefrigerator場合、呼び出しcm.start();rf.start()は同じように機能しcmますが、異なるCoolingMachinesオブジェクトである可能性もあります。そして、そのオブジェクトは、の異なる実装を持つことができますstart()

于 2012-06-18T12:18:19.883 に答える
7

最初の答え:

メソッドのオーバーライドとメソッドのオーバーロードにはポリモーフィズムを使用します。別のクラスで使用される他のクラス メソッドと 2 つのオプション: 最初のメソッドは継承され、2 番目のメソッドは上書きされます。ここでインターフェースを拡張します: それらを使用するか、実装方法: ロジックはそれらを書き込みます。メソッド、クラスの継承に使用されるポリモーフィズム。

2番目の答え:

と の間に違いはcm.start();ありrf.start();ますか?

はい、どちらも互いに完全に異なるオブジェクトです。Java はインターフェイス オブジェクトをサポートしていないため、インターフェイス オブジェクトを作成しないでください。インターフェイス用に作成された最初のオブジェクトと Refrigerator クラス用の 2 番目のオブジェクト。現在 2 番目のオブジェクト。

于 2012-06-18T12:53:42.457 に答える
5

あなたの質問の一般的な部分に対する最も一般的な答え (なぜポリモーフィズムを使用する必要があるのですか?) は、ポリモーフィズムがいくつかの重要なオブジェクト指向設計原則を実現することです。たとえば、次のようになります。

  • コードの再利用: すべての「冷却マシン」に共通のコードを冷却マシンに配置することにより、そのコードを 1 回記述するだけで、そのコードへの編集はすぐに反映されます。

  • 抽象化: 人間の脳は非常に多くのものしか追跡できませんが、カテゴリと階層は得意です。これは、大きなプログラムで何が起こっているかを理解するのに役立ちます。

  • カプセル化: 各クラスは、それが何をしているかの詳細を隠し、基本クラスのインターフェイスに基づいて構築されます。

  • 関心の分離: オブジェクト指向プログラミングの多くは、責任の割り当てに関するものです。誰がそれを担当する予定ですか?特殊な関心事はサブクラスに入ることができます。

したがって、ポリモーフィズムはより大きな oo の全体像の一部にすぎず、それを使用する理由は、「実際の」oo プログラミングを試して実行する場合にのみ意味をなす場合があります。

于 2012-06-18T21:50:05.437 に答える
4

ポリモーフィズムの単純な使用例は、要素 0 が冷蔵庫で要素 1 がエアコンなどの冷却マシンの配列を持つことができるというものです...

trip や start などを呼び出すために、チェックを実行したり、扱っているオブジェクトを確認したりする必要はありません。

これは、ユーザーから入力を取得し、すべてのオブジェクトを反復して同様の関数を呼び出さなければならない場合に、大きな利点となります。

于 2012-06-18T12:21:05.723 に答える
2

オブジェクトをポリモーフィックに使用すると、関連するクラスのファクトリまたはファミリを作成するのにも役立ちます。これは、ファクトリ デザイン パターンの実装方法の重要な部分です。ポリモーフィック ファクトリの非常に基本的な例を次に示します。

public CoolingMachine CreateCoolingMachines(string machineType)
{
    if(machineType == "ref")
        return new Refrigerator();
    //other else ifs to return other types of CoolingMachine family
}

上記のコードの呼び出しの使用法:

CoolingMachine cm = CreateCoolingMachine("AC"); //the cm variable will have a reference to Airconditioner class which is returned by CreateCoolingMachines() method polymorphically

また、具体的なクラス パラメータを使用する以下のようなメソッドがあるとしますRefrigerator

public void UseObject(Refrigerator refObject)
{
    //Implementation to use Refrigerator object only
}

ここで、上記のメソッドの実装をUseObject()最も一般的な基本クラスのパラメーターを使用するように変更すると、呼び出し元のコードは任意のパラメーターをポリモーフィックに渡すことができるようになり、メソッド内で利用できるようになりますUseObject()

public void UseObject(CoolingMachine coolingMachineObject)
{
    //Implementation to use Generic object and all derived objects
}

上記のコードは、他のサブクラスが後で CoolingMachines のファミリに追加される可能性があり、これらの新しいサブクラスのオブジェクトも既存のコードで動作するため、より拡張可能になりました。

于 2012-06-18T12:34:41.847 に答える
2

分かりやすい例を出します。あなたがいくつかのjsonを持っているとしましょう

{"a":[1,2],"sz":"text", "v":3, "f":1.2}

ここで、名前、型、および値を一覧表示するプログラムを使用するとします。各タイプ (a の場合は配列、sz の場合は文字列など) に switch() を使用する代わりに、基本タイプを使用して、そのジョブを実行する関数を呼び出すことができます。また、十数種類のスイッチを使用するよりも CPU 効率が高くなります。

次に、インターフェース上の理由によるプラグイン、ライブラリ、および外部コードがあります。

于 2012-06-18T21:42:38.090 に答える