web-dev-qa-db-ja.com

ポリモーフィズムの利点

多型の利点を探し始めたとき、ここで this の質問で見つけました。しかし、ここで答えを見つけることができませんでした。見つけたいものを教えてください。ここにいくつかのクラスがあります:

_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オブジェクトからRefrigeratortrip()メソッドを呼び出すことができることを完全に理解しましたが、そのメソッドはcmに対して非表示になります。オブジェクト。ここで私の質問は、なぜ多型を使用する必要があるのか​​、なぜ使用する必要があるのか​​です

_CoolingMachines cm = new Refrigerator();
_

私が大丈夫なとき

_Refrigerator rf = new Refrigerator();
_

多態性オブジェクトの効率は良いですか、それとも軽量ですか?これらのオブジェクトの基本的な目的と違いは何ですか? cm.start();rf.start()に違いはありますか?

69
khan

リストを処理するときに便利です...簡単な例:

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

または、メソッドがCoolingMachinesのサブクラスで動作することを許可する場合

71
pgras

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

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

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

58
Jon Skeet

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

28
Naveen

使用したい理由

_CoolingMachines cm = new Refrigerator();
_

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

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

17
Simeon Visser

最初の答え:

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

2番目の答え:

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

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

7

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

  • コードの再利用:すべての「冷却マシン」に共通するコードを冷却マシンに配置することで、そのコードを1回記述するだけで、そのコードの編集をすぐに実行できます。

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

  • カプセル化:各クラスは、実行していることの詳細を隠し、基本クラスのインターフェース上に構築します。

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

したがって、ポリモーフィズムは、より大きなオブジェクト指向の一部に過ぎず、それを使用する理由は、「実際の」オブジェクト指向プログラミングを試みて実行する場合にのみ意味をなすことがあります。

5
Scruffy

ポリモーフィズムの簡単な使用例は、要素0が冷蔵庫で要素1がAirConditionerなどであるcoolingMachinesの配列を持つことができることです...

Tripを呼び出したり開始したりするために、チェックを実行したり、処理しているオブジェクトを確認したりする必要はありません。

これは、ユーザーからの入力を受け取り、すべてのオブジェクトを反復処理し、同様の関数を呼び出す必要がある場合に大きな利点になります。

3

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

_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ファミリに追加できるため、より拡張性が高くなり、これらの新しいサブクラスのオブジェクトも既存のコードで機能します。

2
VS1

わかりやすい例を挙げます。 jsonがあるとしましょう

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

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

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

2
user34537