web-dev-qa-db-ja.com

多態性vsオーバーライドvsオーバーロード

Javaに関して言えば、誰かが尋ねるとき:

多型とは何ですか?

オーバーロードまたはオーバーライドが適切な回答になりますか?

それ以上のことがあると思います。

実装しないでメソッドを定義した抽象基本クラスがあり、そのメソッドをサブクラスで定義した場合でも、それはオーバーライドされますか?

私はオーバーロードは確かに正しい答えではないと思います。

327
Brian G

多態性を表現する最も明確な方法は、抽象基本クラス(またはインターフェース)を使用することです。

public abstract class Human{
   ...
   public abstract void goPee();
}

goPee()メソッドは人間には定義できないため、このクラスは抽象クラスです。これは、サブクラスの男性と女性に対してのみ定義できます。また、人間は抽象的な概念です - 男性でも女性でもない人間を作ることはできません。それはどちらかになるべきです。

そのため、抽象クラスを使用して実装を延期します。

public class Male extends Human{
...
    @Override
    public void goPee(){
        System.out.println("Stand Up");
    }
}

そして

public class Female extends Human{
...
    @Override
    public void goPee(){
        System.out.println("Sit Down");
    }
}

今、私たちは人間でいっぱいの部屋全体におしっこをするように言うことができます。

public static void main(String[] args){
    ArrayList<Human> group = new ArrayList<Human>();
    group.add(new Male());
    group.add(new Female());
    // ... add more...

    // tell the class to take a pee break
    for (Human person : group) person.goPee();
}

これを実行すると次のようになります。

Stand Up
Sit Down
...
872
Chris Cudmore

多態性クラスインスタンスが継承ツリーの別のクラスのインスタンスであるかのように振る舞う能力です。ほとんどの場合、そのクラスインスタンスはその上位クラスの1つです。たとえば、JavaではすべてのクラスがObjectを継承しています。したがって、Object型の変数を作成し、それに任意のクラスのインスタンスを割り当てることができます。

オーバーライドは、他のクラスから継承したクラスで発生する関数の一種です。オーバーライド関数は、基本クラスから継承した関数を「置き換えます」が、そのクラスのインスタンスが多態性を通じて別の型であるふりをしている場合でも呼び出されるようにします。前の例を参照すると、独自のクラスを定義してtoString()関数をオーバーライドすることができます。この関数はObjectから継承されているため、このクラスのインスタンスをObject型の変数にコピーしても使用できます。通常、クラスをObjectにするふりをしているときにtoString()を呼び出すと、実際に起動されるtoStringのバージョンは、Object自体に定義されているバージョンになります。ただし、この関数はオーバーライドなので、クラスインスタンスの実際の型が多態性の背後に隠れている場合でも、クラスからのtoString()の定義が使用されます。

オーバーロードは、名前は同じでパラメータが異なる複数のメソッドを定義することです。これは、オーバーライドまたは多態性とは無関係です。

91

これが擬似C#/ Javaの多態性の例です。

class Animal
{
    abstract string MakeNoise ();
}

class Cat : Animal {
    string MakeNoise () {
        return "Meow";
    }
}

class Dog : Animal {
    string MakeNoise () {
        return "Bark";
    }
}

Main () {
   Animal animal = Zoo.GetAnimal ();
   Console.WriteLine (animal.MakeNoise ());
}

Main関数は動物の種類を知らず、MakeNoise()メソッドの特定の実装の動作に依存します。

編集:ブライアンが私を殴ったようです。おかしい私たちは同じ例を使った。しかし、上記のコードは概念を明確にするのに役立ちます。

43

ポリモーフィズムとは、複数のフォーム、同じオブジェクトが要件に従って異なる操作を実行することを意味します。

多相は2つの方法で達成できます。

  1. メソッドオーバーライド
  2. メソッドオーバーロード

メソッドのオーバーロードは、同じメソッド名を使用して同じクラスに2つ以上のメソッドを記述することを意味しますが、引き渡しパラメーターは異なります。

メソッドのオーバーライドは、異なるクラスでメソッド名を使用することを意味します。つまり、親クラスのメソッドが子クラスで使用されるということです。

Javaでは、多態性を実現するために、スーパークラス参照変数はサブクラスオブジェクトを保持できます。

多態性を実現するには、すべての開発者がプロ​​ジェクト内で同じメソッド名を使用する必要があります。

43
manoj

オーバーライドとオーバーロードの両方を使用して多型を実現します。

1つ以上のサブクラスでオーバーライドされたというメソッドをクラスに含めることができます。このメソッドは、オブジェクトのインスタンス化に使用されたクラスに応じて動作が異なります。

    abstract class Beverage {
       boolean isAcceptableTemperature();
    }

    class Coffee extends Beverage {
       boolean isAcceptableTemperature() { 
           return temperature > 70;
       }
    }

    class Wine extends Beverage {
       boolean isAcceptableTemperature() { 
           return temperature < 10;
       }
    }

複数の引数セットを持つオーバーロードというメソッドもあります。このメソッドは、渡された引数の種類に基づいてさまざまな処理を実行します。

    class Server {
        public void pour (Coffee liquid) {
            new Cup().fillToTopWith(liquid);
        }

        public void pour (Wine liquid) {
            new WineGlass().fillHalfwayWith(liquid);
        }

        public void pour (Lemonade liquid, boolean ice) {
            Glass glass = new Glass();
            if (ice) {
                glass.fillToTopWith(new Ice());
            }
            glass.fillToTopWith(liquid);
        }
    }
39

あなたは過負荷が答えではないことは正しいです。

どちらも優先されません。オーバーライドは、多態性を得るための手段です。多態性とは、オブジェクトがそのタイプに基づいて動作を変える能力です。これは、ポリモーフィズムを示すオブジェクトの呼び出し元が、そのオブジェクトがどの特定のタイプであるかを認識していない場合に最もよく実証されます。

13
Alex B

具体的には、オーバーロードまたはオーバーライドと言っても全体像はわかりません。ポリモーフィズムとは、オブジェクトがその型に基づいてその振る舞いを特殊化する能力です。

同じ名前を持つメソッドが異なる振る舞いをして異なるパラメータ型を与えることができる場合には、オーバーロードが多態性(パラメトリック多態性)の一形態であるという点で、私はここでいくつかの答えに同意しません。良い例はオペレータの過負荷です。文字列やintなど、さまざまなタイプのパラメータを受け入れるように "+"を定義することができ、それらのタイプに基づいて、 "+"の動作は異なります。

多態性には継承メソッドやオーバーライドメソッドも含まれますが、基本型では抽象メソッドまたは仮想メソッドを使用できます。継承ベースの多態性に関しては、Javaは単一クラスの継承のみをサポートしており、多態性の振る舞いを基本型の単一チェーンのそれに限定しています。 Javaは、さらに別の形の多態的な振る舞いである複数のインターフェースの実装をサポートしています。

10
Peter Meyer

多態性は単に「多形態」を意味します。

継承を実現するために継承を要求するものではありません。継承ではないインタフェース実装は、多態性のニーズを満たすためです。おそらく、インターフェースの実装は、継承よりも「良い」多態性のニーズに応えます。

たとえば、飛ぶことができるものすべてを記述するためのスーパークラスを作成しますか。そうは思わない。あなたはフライトを記述しそれをそのままにしておくインターフェースを作成するために最も役立たれるでしょう。

したがって、インタフェースは振る舞いを記述し、メソッド名は(プログラマにとって)振る舞いを記述しているので、メソッドのオーバーロードをより少ない形の多態性として考えることはそれほど難しくありません。

7
BillC

古典的な例では、犬と猫は動物であり、動物はメソッドmakeNoiseを持っています。私はそれらに対してmakeNoiseを呼び出す一連の動物を通して反復することができ、それらがそこでそれぞれの実装をするだろうと期待します。

呼び出しコードは、彼らがどんな特定の動物であるかを知る必要はありません。

多態性と私が考えているのはその通りです。

6
Brian G

どちらでもない:

オーバーロードは、異なるパラメータをとる同じ関数名があるときです。

オーバーライドとは、子クラスが親のメソッドを独自のメソッドに置き換える場合です(これ自体は多態性を構成するものではありません)。

多型は後期結合である。基本クラス(親)メソッドが呼び出されていますが、実行時までアプリケーションは実際のオブジェクトが何であるかを認識していません - メソッドが異なる子クラスかもしれません。これは、基本クラスが定義されている場所では任意の子クラスを使用できるためです。

Javaでは、コレクションライブラリを使って多態性がよくわかります。

int countStuff(List stuff) {
  return stuff.size();
}

Listは基本クラスなので、Listのように機能する限り、リンクリスト、ベクトル、配列、カスタムリストの実装のいずれを使用している場合でも、コンパイラはその手がかりを得ません。

List myStuff = new MyTotallyAwesomeList();
int result = countStuff(myStuff);

あなたが過負荷になっていたらあなたは持っているでしょう:

int countStuff(LinkedList stuff) {...}
int countStuff(ArrayList stuff) {...}
int countStuff(MyTotallyAwesomeList stuff) {...}
etc...

そして、正しいバージョンのcountStuff()がコンパイラーによって選択され、パラメーターが一致します。

4
jpeacock

多態性は、オブジェクトが複数の形式で表示される機能です。これには、継承と仮想関数を使用して、交換可能なオブジェクトのファミリーを構築することが含まれます。基本クラスには、アプリケーションの指示に従って実装されていない、またはデフォルト実装の仮想関数のプロトタイプが含まれています。さまざまな派生クラスは、それぞれ異なる動作に影響を与えるために実装が異なります。

4
mxg

オーバーロードという用語は、同じ名前を持つものの複数のバージョン、通常は異なるパラメータリストを持つメソッドを持つことを意味します。

public int DoSomething(int objectId) { ... }
public int DoSomething(string objectName) { ... }

そのため、これらの関数でも同じことができますが、IDまたは名前を指定して呼び出すことができます。継承、抽象クラスなどとは関係ありません。

あなたがあなたの質問で説明したように、上書きすることは通常、多態性を指します

3
Clyde

私はみんなあなたが概念を混合していると思います。 多態性は、実行時にオブジェクトが異なる動作をする能力です。これを実現するには、2つの必要条件があります。

  1. 遅延バインディング
  2. 継承

オーバーロードと言ったことは、使用している言語によってオーバーライドとは異なることを意味します。例えば、Javaでは存在しませんオーバーライドしかしオーバーロードオーバーロード基本クラスとは異なるシグネチャを持つメソッドがサブクラスで利用可能です。そうでなければ、それらはオーバーライドされたになります(オブジェクトの外側からあなたの基本クラスのメソッドを呼び出す方法がないという事実を今すぐ言ってください)。

しかしC++ではそうではありません。シグネチャが同じであるかどうかにかかわらず、任意のオーバーロードされたメソッド(独立した量、異なるタイプ)も同様にオーバーライドつまり、基本クラスのメソッドは、サブクラスオブジェクトの外部から呼び出されると、サブクラスで使用できなくなります。

だから答えはJavaの使用について話しているときですオーバーロード。それはC + +で起こるように他の言語では異なる場合があります

2
user1154840

多態性については、この記事で既に詳細に説明されていますが、なぜその一部なのかをもっと強調したいと思います。

多態性がどのようなOOP言語で重要なのか.

継承/多態性の有無にかかわらず、テレビ用のシンプルなアプリケーションを作成してみましょう。アプリケーションの各バージョンを投稿し、私たちは小さな回顧展を行います。

あなたがテレビ会社のソフトウェアエンジニアであり、音量、明るさ、色の各コントローラー用のソフトウェアを作成してユーザーコマンドで値を増減するように指示されたとします。

追加することで、これらの各機能のクラスを書くことから始めます。

  1. set: - コントローラの値を設定します(これにコントローラ固有のコードがあると仮定します)。
  2. get: - コントローラの値を取得します(これにコントローラ固有のコードがあるとします)
  3. 調整: - 入力を検証してコントローラを設定する(一般的な検証。コントローラとは無関係)
  4. コントローラとのユーザ入力マッピング: - ユーザ入力を取得し、それに応じてコントローラを呼び出す。

アプリケーションバージョン1

import Java.util.Scanner;    
class VolumeControllerV1 {
    private int value;
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class  BrightnessControllerV1 {
    private int value;
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class ColourControllerV1    {
    private int value;
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}

/*
 *       There can be n number of controllers
 * */
public class TvApplicationV1 {
    public static void main(String[] args)  {
        VolumeControllerV1 volumeControllerV1 = new VolumeControllerV1();
        BrightnessControllerV1 brightnessControllerV1 = new BrightnessControllerV1();
        ColourControllerV1 colourControllerV1 = new ColourControllerV1();


        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println("Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV1.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV1.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV1.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV1.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV1.adjust(5);
                    break;
                }
                case 6: {
                colourControllerV1.adjust(-5);
                break;
            }
            default:
                System.out.println("Shutting down...........");
                break OUTER;
        }

    }
    }
}

これで、実用的なアプリケーションの最初のバージョンをデプロイする準備が整いました。これまでに行った作業を分析する時間です。

TVアプリケーションバージョン1の問題

  1. Adjust(int value)コードは3つのクラスすべてで重複しています。コードの重複を最小限に抑えたいと思います。 (しかし、あなたは共通コードを考えず、コードの重複を避けるためにそれをあるスーパークラスに移動しました)

あなたのアプリケーションが期待通りに動く限り、あなたはそれで生きることにします。

時々、あなたの上司はあなたに戻ってきて、既存のアプリケーションにリセット機能を追加するようにあなたに求めます。リセットすると、3つの3つのコントローラーすべてがそれぞれのデフォルト値に設定されます。

新しい機能のための新しいクラス(ResetFunctionV2)を書き始め、この新しい機能のためのユーザー入力マッピングコードをマッピングします。

アプリケーションバージョン2

import Java.util.Scanner;
class VolumeControllerV2    {

    private int defaultValue = 25;
    private int value;

    int getDefaultValue() {
        return defaultValue;
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class  BrightnessControllerV2   {

    private int defaultValue = 50;
    private int value;
    int get()    {
        return value;
    }
    int getDefaultValue() {
        return defaultValue;
    }
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class ColourControllerV2    {

    private int defaultValue = 40;
    private int value;
    int get()    {
        return value;
    }
    int getDefaultValue() {
        return defaultValue;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}

class ResetFunctionV2 {

    private VolumeControllerV2 volumeControllerV2 ;
    private BrightnessControllerV2 brightnessControllerV2;
    private ColourControllerV2 colourControllerV2;

    ResetFunctionV2(VolumeControllerV2 volumeControllerV2, BrightnessControllerV2 brightnessControllerV2, ColourControllerV2 colourControllerV2)  {
        this.volumeControllerV2 = volumeControllerV2;
        this.brightnessControllerV2 = brightnessControllerV2;
        this.colourControllerV2 = colourControllerV2;
    }
    void onReset()    {
        volumeControllerV2.set(volumeControllerV2.getDefaultValue());
        brightnessControllerV2.set(brightnessControllerV2.getDefaultValue());
        colourControllerV2.set(colourControllerV2.getDefaultValue());
    }
}
/*
 *       so on
 *       There can be n number of controllers
 *
 * */
public class TvApplicationV2 {
    public static void main(String[] args)  {
        VolumeControllerV2 volumeControllerV2 = new VolumeControllerV2();
        BrightnessControllerV2 brightnessControllerV2 = new BrightnessControllerV2();
        ColourControllerV2 colourControllerV2 = new ColourControllerV2();

        ResetFunctionV2 resetFunctionV2 = new ResetFunctionV2(volumeControllerV2, brightnessControllerV2, colourControllerV2);

        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV2.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV2.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV2.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV2.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV2.adjust(5);
                    break;
                }
                case 6: {
                    colourControllerV2.adjust(-5);
                    break;
                }
                case 7: {
                    resetFunctionV2.onReset();
                    break;
                }
                default:
                    System.out.println("Shutting down...........");
                    break OUTER;
            }

        }
    }
}

それであなたはあなたのアプリケーションをリセット機能で準備ができています。しかし、今、あなたはそれを理解し始めます

TVアプリケーションバージョン2の問題

  1. 製品に新しいコントローラが導入された場合は、リセット機能コードを変更する必要があります。
  2. コントローラの数が非常に多くなった場合、コントローラの参照を保持することに問題があるでしょう。
  3. リセット機能コードは、(デフォルト値を取得および設定するために)すべてのコントローラクラスのコードと密接に関連しています。
  4. リセットフィーチャクラス(ResetFunctionV2)は、望ましくないコントローラクラスの(adjust)の他のメソッドにアクセスできます。

同時に、Bossから、起動時に各コントローラがインターネットを介して会社のホストドライバリポジトリから最新バージョンのドライバをチェックする必要があるという機能を追加する必要があるかもしれないと聞いています。

これで、追加されるこの新機能はリセット機能に似ていると考え始め、アプリケーションの問題を解決しないとアプリケーションの問題(V2)が倍増することになります。

Javaの多態性を利用して新しい抽象クラス(ControllerV3)を追加するために、継承を使用することを考え始めます。

  1. Getおよびsetメソッドのシグネチャを宣言します。
  2. 以前すべてのコントローラー間で複製されたadjustメソッドの実装を含みます。
  3. 多態性を利用してリセット機能を簡単に実装できるようにsetDefaultメソッドを宣言します。

これらの改善により、TVアプリケーションのバージョン3が用意されました。

アプリケーションバージョン3

import Java.util.ArrayList;
import Java.util.List;
import Java.util.Scanner;

abstract class ControllerV3 {
    abstract void set(int value);
    abstract int get();
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
    abstract void setDefault();
}
class VolumeControllerV3 extends ControllerV3   {

    private int defaultValue = 25;
    private int value;

    public void setDefault() {
        set(defaultValue);
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
}
class  BrightnessControllerV3  extends ControllerV3   {

    private int defaultValue = 50;
    private int value;

    public void setDefault() {
        set(defaultValue);
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }
}
class ColourControllerV3 extends ControllerV3   {

    private int defaultValue = 40;
    private int value;

    public void setDefault() {
        set(defaultValue);
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
}

class ResetFunctionV3 {

    private List<ControllerV3> controllers = null;

    ResetFunctionV3(List<ControllerV3> controllers)  {
        this.controllers = controllers;
    }
    void onReset()    {
        for (ControllerV3 controllerV3 :this.controllers)  {
            controllerV3.setDefault();
        }
    }
}
/*
 *       so on
 *       There can be n number of controllers
 *
 * */
public class TvApplicationV3 {
    public static void main(String[] args)  {
        VolumeControllerV3 volumeControllerV3 = new VolumeControllerV3();
        BrightnessControllerV3 brightnessControllerV3 = new BrightnessControllerV3();
        ColourControllerV3 colourControllerV3 = new ColourControllerV3();

        List<ControllerV3> controllerV3s = new ArrayList<>();
        controllerV3s.add(volumeControllerV3);
        controllerV3s.add(brightnessControllerV3);
        controllerV3s.add(colourControllerV3);

        ResetFunctionV3 resetFunctionV3 = new ResetFunctionV3(controllerV3s);

        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV3.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV3.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV3.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV3.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV3.adjust(5);
                    break;
                }
                case 6: {
                    colourControllerV3.adjust(-5);
                    break;
                }
                case 7: {
                    resetFunctionV3.onReset();
                    break;
                }
                default:
                    System.out.println("Shutting down...........");
                    break OUTER;
            }

        }
    }
}

V2のissueリストにリストされているissueの大部分は、以下を除いて対処されていますが

TVアプリケーションバージョン3の問題

  1. リセットフィーチャクラス(ResetFunctionV3)は、望ましくないコントローラクラス(adjust)の他のメソッドにアクセスできます。

繰り返しますが、この問題を解決することを考えてください。今度は、実装するための別の機能(起動時のドライバの更新)もあります。修正しないと、新機能にも反映されます。

だからあなたは抽象クラスで定義された契約を分割して2つのインタフェースを書く:

  1. 機能をリセットします。
  2. ドライバーのアップデート.

そして、あなたの最初の具象クラスに以下のようにそれらを実装させます

アプリケーションバージョン4

import Java.util.ArrayList;
import Java.util.List;
import Java.util.Scanner;

interface OnReset {
    void setDefault();
}
interface OnStart {
    void checkForDriverUpdate();
}
abstract class ControllerV4 implements OnReset,OnStart {
    abstract void set(int value);
    abstract int get();
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}

class VolumeControllerV4 extends ControllerV4 {

    private int defaultValue = 25;
    private int value;
    @Override
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
    @Override
    public void setDefault() {
        set(defaultValue);
    }

    @Override
    public void checkForDriverUpdate()    {
        System.out.println("Checking driver update for VolumeController .... Done");
    }
}
class  BrightnessControllerV4 extends ControllerV4 {

    private int defaultValue = 50;
    private int value;
    @Override
    int get()    {
        return value;
    }
    @Override
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }

    @Override
    public void setDefault() {
        set(defaultValue);
    }

    @Override
    public void checkForDriverUpdate()    {
        System.out.println("Checking driver update for BrightnessController .... Done");
    }
}
class ColourControllerV4 extends ControllerV4 {

    private int defaultValue = 40;
    private int value;
    @Override
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
    @Override
    public void setDefault() {
        set(defaultValue);
    }

    @Override
    public void checkForDriverUpdate()    {
        System.out.println("Checking driver update for ColourController .... Done");
    }
}
class ResetFunctionV4 {

    private List<OnReset> controllers = null;

    ResetFunctionV4(List<OnReset> controllers)  {
        this.controllers = controllers;
    }
    void onReset()    {
        for (OnReset onreset :this.controllers)  {
            onreset.setDefault();
        }
    }
}
class InitializeDeviceV4 {

    private List<OnStart> controllers = null;

    InitializeDeviceV4(List<OnStart> controllers)  {
        this.controllers = controllers;
    }
    void initialize()    {
        for (OnStart onStart :this.controllers)  {
            onStart.checkForDriverUpdate();
        }
    }
}
/*
*       so on
*       There can be n number of controllers
*
* */
public class TvApplicationV4 {
    public static void main(String[] args)  {
        VolumeControllerV4 volumeControllerV4 = new VolumeControllerV4();
        BrightnessControllerV4 brightnessControllerV4 = new BrightnessControllerV4();
        ColourControllerV4 colourControllerV4 = new ColourControllerV4();
        List<ControllerV4> controllerV4s = new ArrayList<>();
        controllerV4s.add(brightnessControllerV4);
        controllerV4s.add(volumeControllerV4);
        controllerV4s.add(colourControllerV4);

        List<OnStart> controllersToInitialize = new ArrayList<>();
        controllersToInitialize.addAll(controllerV4s);
        InitializeDeviceV4 initializeDeviceV4 = new InitializeDeviceV4(controllersToInitialize);
        initializeDeviceV4.initialize();

        List<OnReset> controllersToReset = new ArrayList<>();
        controllersToReset.addAll(controllerV4s);
        ResetFunctionV4 resetFunctionV4 = new ResetFunctionV4(controllersToReset);

        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV4.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV4.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV4.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV4.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV4.adjust(5);
                    break;
                }
                case 6: {
                    colourControllerV4.adjust(-5);
                    break;
                }
                case 7: {
                    resetFunctionV4.onReset();
                    break;
                }
                default:
                    System.out.println("Shutting down...........");
                    break OUTER;
            }

        }
    }
}

これで、あなたが直面していた問題のすべてが解決され、継承とポリモーフィズムを使用することで、

  1. アプリケーションのさまざまな部分を疎結合に保ちます(リセットまたはドライバ更新機能コンポーネントは、実際のコントローラクラス(音量、明るさおよび色)を認識する必要はなく、OnResetまたはOnStartを実装するクラスはリセットまたはドライバ更新機能を受け入れます)。それぞれのコンポーネント)。
  2. アプリケーションの機能強化が簡単になります(コントローラを新しく追加しても、リセットやドライバ更新機能コンポーネントに影響はありません。新しいコンポーネントを追加するのは非常に簡単です)。
  3. 抽象化レイヤを保持します(リセット機能ではコントローラのsetDefaultメソッドのみが表示され、リセット機能ではコントローラのcheckForDriverUpdateメソッドのみが表示されます)。

お役に立てれば :-)

2
Developer

多型とは何ですか?

Javaから チュートリアル

多型の辞書による定義は、生物や種がさまざまな形や段階を持つことができる生物学の原則を指します。この原則は、オブジェクト指向プログラミングやJava言語などの言語にも適用できます。 クラスのサブクラスは、独自の独自の動作を定義しながら、親クラスと同じ機能をいくつか共有できます。

例と定義を考慮することによって、をオーバーライドする答えを受け入れるべきです。

2番目のクエリについて

実装のないメソッドを定義した抽象基本クラスがあり、そのメソッドをサブクラスで定義した場合、それはまだオーバーライドされていますか?

それは上書きと呼ばれるべきです。

この例を見て、さまざまなタイプのオーバーライドを理解してください。

  1. 基本クラスは実装を提供せず、サブクラスは完全なメソッドをオーバーライドする必要があります - (abstract)
  2. 基本クラスはデフォルトの実装を提供し、サブクラスは動作を変更できます
  3. サブクラスは、最初のステートメントとしてsuper.methodName()を呼び出すことによって基本クラスの実装に拡張を追加します
  4. 基本クラスはアルゴリズム(テンプレートメソッド)の構造を定義し、サブクラスはアルゴリズムの一部をオーバーライドします

コードスニペット:

import Java.util.HashMap;

abstract class Game implements Runnable{

    protected boolean runGame = true;
    protected Player player1 = null;
    protected Player player2 = null;
    protected Player currentPlayer = null;

    public Game(){
        player1 = new Player("Player 1");
        player2 = new Player("Player 2");
        currentPlayer = player1;
        initializeGame();
    }

    /* Type 1: Let subclass define own implementation. Base class defines abstract method to force
        sub-classes to define implementation    
    */

    protected abstract void initializeGame();

    /* Type 2: Sub-class can change the behaviour. If not, base class behaviour is applicable */
    protected void logTimeBetweenMoves(Player player){
        System.out.println("Base class: Move Duration: player.PlayerActTime - player.MoveShownTime");
    }

    /* Type 3: Base class provides implementation. Sub-class can enhance base class implementation by calling
        super.methodName() in first line of the child class method and specific implementation later */
    protected void logGameStatistics(){
        System.out.println("Base class: logGameStatistics:");
    }
    /* Type 4: Template method: Structure of base class can't be changed but sub-class can some part of behaviour */
    protected void runGame() throws Exception{
        System.out.println("Base class: Defining the flow for Game:");  
        while ( runGame) {
            /*
            1. Set current player
            2. Get Player Move
            */
            validatePlayerMove(currentPlayer);  
            logTimeBetweenMoves(currentPlayer);
            Thread.sleep(500);
            setNextPlayer();
        }
        logGameStatistics();
    }
    /* sub-part of the template method, which define child class behaviour */
    protected abstract void validatePlayerMove(Player p);

    protected void setRunGame(boolean status){
        this.runGame = status;
    }
    public void setCurrentPlayer(Player p){
        this.currentPlayer = p;
    }
    public void setNextPlayer(){
        if ( currentPlayer == player1) {
            currentPlayer = player2;
        }else{
            currentPlayer = player1;
        }
    }
    public void run(){
        try{
            runGame();
        }catch(Exception err){
            err.printStackTrace();
        }
    }
}

class Player{
    String name;
    Player(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
}

/* Concrete Game implementation  */
class Chess extends Game{
    public Chess(){
        super();
    }
    public void initializeGame(){
        System.out.println("Child class: Initialized Chess game");
    }
    protected void validatePlayerMove(Player p){
        System.out.println("Child class: Validate Chess move:"+p.getName());
    }
    protected void logGameStatistics(){
        super.logGameStatistics();
        System.out.println("Child class: Add Chess specific logGameStatistics:");
    }
}
class TicTacToe extends Game{
    public TicTacToe(){
        super();
    }
    public void initializeGame(){
        System.out.println("Child class: Initialized TicTacToe game");
    }
    protected void validatePlayerMove(Player p){
        System.out.println("Child class: Validate TicTacToe move:"+p.getName());
    }
}

public class Polymorphism{
    public static void main(String args[]){
        try{

            Game game = new Chess();
            Thread t1 = new Thread(game);
            t1.start();
            Thread.sleep(1000);
            game.setRunGame(false);
            Thread.sleep(1000);

            game = new TicTacToe();
            Thread t2 = new Thread(game);
            t2.start();
            Thread.sleep(1000);
            game.setRunGame(false);

        }catch(Exception err){
            err.printStackTrace();
        }       
    }
}

出力:

Child class: Initialized Chess game
Base class: Defining the flow for Game:
Child class: Validate Chess move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate Chess move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:
Child class: Add Chess specific logGameStatistics:
Child class: Initialized TicTacToe game
Base class: Defining the flow for Game:
Child class: Validate TicTacToe move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate TicTacToe move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:
2
Ravindra babu

多重定義とは、名前は同じだがパラメータが異なる2つのメソッドを定義するときです。

オーバーライドとは、サブクラス内の同じ名前の関数を介して基本クラスの動作を変更する場所です。

したがって、ポリモーフィズムはオーバーライドに関連していますが、実際にはオーバーロードではありません。

しかし、「多態性とは何ですか」という質問に対して、誰かが私に「上書きする」という単純な答えを出した場合。さらなる説明をお願いします。

2
Matt

オーバーライドは、上位レベルのメソッド(スーパーメソッド)と同じ名前とシグネチャを持つメソッドを宣言することによって継承されたメソッドを非表示にすることに似ています。これにより、クラスに多相的な動作が追加されます。言い換えれば、どのレベルのメソッドを呼び出すかは、コンパイル時ではなく実行時に決定されます。これがインタフェースと実装の概念につながります。

2
Genjuro

ポリモーフィズムは意味が関係している限りでは可能性が高いです... JavaのOVERRIDINGに

さまざまな状況でのSAMEオブジェクトのさまざまな動作に関するすべてです(プログラミングの方法では、さまざまな引数を呼び出すことができます)。

以下の例は理解するのに役立つと思います。PURE Javaコードではありませんが...

     public void See(Friend)
     {
        System.out.println("Talk");
     }

しかし、私たちが議論を変えると...行動は変わるでしょう...

     public void See(Enemy)
     {
        System.out.println("Run");
     }

人(ここでは「オブジェクト」)は同じです...

1
Rajan

多態性はオブジェクトの複数の実装であるか、またはオブジェクトの複数の形式を言うことができます。抽象基底クラスとしてクラスAnimalsがあり、それに動物の動きを定義するmovement()というメソッドがあるとしましょう。今、実際には私たちには異なる種類の動物があり、それらは異なる動きをします。それらのいくつかは2本の足、4本は4本、そして何もないものなどです。地球上の各動物の異なるmovement()を定義するために、多型を適用する必要があります。ただし、さらにクラスを定義する必要があります。つまり、クラスDogsCatsFishなどです。次に、これらのクラスを基本クラスAnimalsから拡張し、そのメソッドmovement()を各動物に基づく新しい移動機能でオーバーライドする必要があります。それを実現するためにInterfacesを使うこともできます。ここでのキーワードはオーバーライドされています。オーバーロードは異なり、多態性とは見なされません。多重定義では、「同じ名前で」、同じオブジェクトまたはクラスに異なるパラメータで複数のメソッドを定義できます。

1
SolidSnake

多態性は、単一のインターフェースを使用することによって言語が異なるオブジェクトを一様に扱う能力に関連しています。このように、それはオーバーライドに関連しているので、インターフェース(または基本クラス)は多態性であり、実装者はオーバーライドするオブジェクトです(同じメダルの2つの面)。

とにかく、2つの用語の違いはc ++のような他の言語を使ってよりよく説明されます:c ++の多態的なオブジェクトは基底関数が仮想であればJavaの対応物として振る舞います 静的に、そして真の型は実行時にチェックされないので、多態性はそれにアクセスするために使用されるインタフェースに依存してオブジェクトが異なって振る舞う能力を含みます。擬似コードで例を作ってみましょう:

class animal {
    public void makeRumor(){
        print("thump");
    }
}
class dog extends animal {
    public void makeRumor(){
        print("woff");
    }
}

animal a = new dog();
dog b = new dog();

a.makeRumor() -> prints thump
b.makeRumor() -> prints woff

(makeRumorは仮想ではないと仮定します)

Javaはこのレベルの多態性(オブジェクトスライスとも呼ばれる)を本当に提供していません。

動物a =新しい犬();犬b =新しい犬();

a.makeRumor() -> prints thump
b.makeRumor() -> prints woff

どちらの場合も、aとbがクラスdogを参照しているため、woff ..だけが表示されます。

0
import Java.io.IOException;

class Super {

    protected Super getClassName(Super s) throws IOException {
        System.out.println(this.getClass().getSimpleName() + " - I'm parent");
        return null;
    }

}

class SubOne extends Super {

    @Override
    protected Super getClassName(Super s)  {
        System.out.println(this.getClass().getSimpleName() + " - I'm Perfect Overriding");
        return null;
    }

}

class SubTwo extends Super {

    @Override
    protected Super getClassName(Super s) throws NullPointerException {
        System.out.println(this.getClass().getSimpleName() + " - I'm Overriding and Throwing Runtime Exception");
        return null;
    }

}

class SubThree extends Super {

    @Override
    protected SubThree getClassName(Super s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Returning SubClass Type");
        return null;
    }

}

class SubFour extends Super {

    @Override
    protected Super getClassName(Super s) throws IOException {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Throwing Narrower Exception ");
        return null;
    }

}

class SubFive extends Super {

    @Override
    public Super getClassName(Super s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and have broader Access ");
        return null;
    }

}

class SubSix extends Super {

    public Super getClassName(Super s, String ol) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading ");
        return null;
    }

}

class SubSeven extends Super {

    public Super getClassName(SubSeven s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading because Method signature (Argument) changed.");
        return null;
    }

}

public class Test{

    public static void main(String[] args) throws Exception {

        System.out.println("Overriding\n");

        Super s1 = new SubOne(); s1.getClassName(null);

        Super s2 = new SubTwo(); s2.getClassName(null);

        Super s3 = new SubThree(); s3.getClassName(null);

        Super s4 = new SubFour(); s4.getClassName(null);

        Super s5 = new SubFive(); s5.getClassName(null);

        System.out.println("Overloading\n");

        SubSix s6 = new SubSix(); s6.getClassName(null, null);

        s6 = new SubSix(); s6.getClassName(null);

        SubSeven s7 = new SubSeven(); s7.getClassName(s7);

        s7 = new SubSeven(); s7.getClassName(new Super());

    }
}
0
bharanitharan