371

Javaに関して、誰かが尋ねると:

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

オーバーロードまたはオーバーライドは受け入れられる答えでしょうか?

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

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

過負荷は確かに正しい答えではないと思います。

4

21 に答える 21

933

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

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

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

したがって、抽象クラスを使用して実装を延期します。

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
...
于 2008-09-30T20:33:51.040 に答える
99

ポリモーフィズムとは、クラス インスタンスが、継承ツリー内の別のクラス (ほとんどの場合、その祖先クラスの 1 つ) のインスタンスであるかのように動作する機能です。たとえば、Java では、すべてのクラスが Object から継承されます。したがって、タイプ Object の変数を作成し、それに任意のクラスのインスタンスを割り当てることができます。

オーバーライド_別のクラスから継承するクラスで発生する関数のタイプです。オーバーライド関数は、基本クラスから継承された関数を「置換」しますが、そのクラスのインスタンスがポリモーフィズムによって別の型であると偽っている場合でも呼び出されるようにします。前の例を参照すると、独自のクラスを定義して toString() 関数をオーバーライドできます。この関数は Object から継承されているため、このクラスのインスタンスを Object 型の変数にコピーしても引き続き使用できます。通常、オブジェクトのふりをしているクラスで toString() を呼び出すと、実際に起動する toString のバージョンは、オブジェクト自体で定義されたバージョンになります。ただし、この関数はオーバーライドであるため、クラス インスタンスが「

オーバーロードは、同じ名前で異なるパラメータを持つ複数のメソッドを定義するアクションです。オーバーライドやポリモーフィズムとは無関係です。

于 2008-09-30T19:51:18.303 に答える
57

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

ポリモーフィズムは、次の 2 つの方法を使用して実現できます。

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

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

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

Java では、ポリモーフィズムを実現するために、スーパー クラス参照変数がサブ クラス オブジェクトを保持できます。

ポリモーフィズムを実現するには、すべての開発者がプロ​​ジェクトで同じメソッド名を使用する必要があります。

于 2012-10-21T05:07:45.327 に答える
45

ポリモーフィズムを実現するために、オーバーライドとオーバーロードの両方が使用されます。

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

    abstract class Beverage {
       boolean isAcceptableTemperature();
    }

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

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

2 つ以上の引数セットでオーバーロードされたメソッドを持つこともでき ます。このメソッドは、渡された引数のタイプに基づいてさまざまなことを行います。

    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);
        }
    }
于 2008-09-30T19:42:37.950 に答える
41

疑似 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() メソッドの特定の実装の動作に依存します。

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

于 2008-09-30T19:41:50.993 に答える
15

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

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

于 2008-09-30T19:35:05.003 に答える
11

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

ここでの回答のいくつかには同意しません。オーバーロードは、同じ名前のメソッドが異なるパラメーターの型を与えると異なる動作をする可能性がある場合のポリモーフィズム (パラメトリック ポリモーフィズム) の一種です。良い例は、演算子のオーバーロードです。"+" を定義して、さまざまなタイプのパラメーター (文字列または int など) を受け入れることができます。これらのタイプに基づいて、"+" は異なる動作をします。

ポリモーフィズムには継承とオーバーライド メソッドも含まれますが、それらは基本型で抽象的または仮想的である可能性があります。継承ベースのポリモーフィズムに関しては、Java は単一クラスの継承のみをサポートし、ポリモーフィックな動作を基本型の単一チェーンの動作に制限しています。Java は、ポリモーフィック動作のさらに別の形式である複数のインターフェイスの実装をサポートしています。

于 2008-09-30T19:51:19.863 に答える
7

ポリモーフィズムとは、単に「多くのフォーム」を意味します。

達成するために継承を必要としません...継承ではないインターフェイスの実装は、ポリモーフィックなニーズに対応します。おそらく、インターフェイスの実装は、継承よりも「優れた」ポリモーフィックなニーズに応えます。

たとえば、飛ぶことができるすべてのものを記述するスーパークラスを作成しますか? ないと思うべきです。フライトを説明するインターフェースを作成し、そのままにしておくのが最善の方法です。

したがって、インターフェイスは振る舞いを記述し、メソッド名は (プログラマーにとって) 振る舞いを記述するため、メソッドのオーバーロードをポリモーフィズムのより少ない形式と見なすことは、それほど難しいことではありません。

于 2010-12-20T05:02:32.547 に答える
6

古典的な例では、犬と猫は動物であり、動物にはメソッド makeNoise があります。動物の配列を反復して makeNoise を呼び出し、それぞれの実装を行うことを期待できます。

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

それがポリモーフィズムと私が考えるものです。

于 2008-09-30T19:37:58.210 に答える
4

ない:

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

オーバーライドとは、子クラスが親のメソッドを独自のメソッドに置き換えることです (これ自体はポリモーフィズムを構成しません)。

ポリモーフィズムは遅延バインディングです。たとえば、基本クラス (親) メソッドが呼び出されますが、実行時までアプリケーションは実際のオブジェクトが何であるかを認識しません。メソッドが異なる子クラスである可能性があります。これは、基本クラスが定義されている場所で任意の子クラスを使用できるためです。

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() の正しいバージョンが、パラメーターに一致するようにコンパイラーによって選択されます。

于 2008-09-30T19:44:34.497 に答える
4

オーバーロードは、同じ名前で異なるパラメーターを持つ2つのメソッドを定義する場合です

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

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

しかし、誰かが「ポリモーフィズムとは何ですか?」という質問に対して「オーバーライドする」という簡単な答えをくれたとしたら、さらに説明を求めます。

于 2008-09-30T19:35:14.537 に答える
4

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

于 2008-09-30T19:36:05.253 に答える
3

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

Javaチュートリアルから

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

例と定義を考慮すると、オーバーライドは回答として受け入れられるはずです。

2番目のクエリについて:

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

それはオーバーライドと呼ばれるべきです。

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

  1. 基本クラスは実装を提供せず、サブクラスは完全なメソッドをオーバーライドする必要があります - (抽象)
  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:
于 2016-09-16T13:37:09.097 に答える
2

ポリモーフィズムは、オブジェクトの複数の実装、またはオブジェクトの複数の形式と言えます。Animals抽象基本クラスとしてクラスがあり、動物の移動方法を定義するメソッドが呼び出されてmovement()いるとします。実際には、さまざまな種類の動物がいて、それらの動きも異なります。また、2 本足の動物、4 本足の動物、足のない動物などもいます。movement()地球上の各動物の違いを定義するには、ポリモーフィズムを適用する必要があります。ただし、より多くのクラス、つまりクラスDogs Cats Fishなどを定義する必要があります。次に、これらのクラスを基本クラスから拡張し、そのメソッドを、所有している各動物に基づいた新しい移動機能でAnimalsオーバーライドする必要があります。movement()使用することもできますInterfacesそれを達成するために。ここでのキーワードはオーバーライドです。オーバーロードは異なり、ポリモーフィズムとは見なされません。オーバーロードを使用すると、「同じ名前で」複数のメソッドを定義できますが、同じオブジェクトまたはクラスで異なるパラメーターを使用できます。

于 2013-09-15T22:37:13.643 に答える
2

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

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

したがって、これらの関数は同じことを行う可能性がありますが、ID または名前で呼び出すオプションがあります。継承、抽象クラスなどとは関係ありません。

オーバーライドは通常、質問で説明したように、ポリモーフィズムを指します

于 2008-09-30T19:33:12.093 に答える
2

皆さんはコンセプトを混ぜていると思います。ポリモーフィズムとは、オブジェクトが実行時に異なる動作をする能力です。これを実現するには、次の 2 つの要件が必要です。

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

オーバーロードとは、使用している言語によってはオーバーライドとは異なる意味を持つと言いました。たとえば、Java ではオーバーライドは存在しませんが、オーバーロードは存在しません。サブクラスでは、基本クラスとは異なる署名を持つオーバーロードされたメソッドを使用できます。そうしないと、それらはオーバーライドされます (オブジェクトの外部から基本クラスのメソッドを呼び出す方法がないという事実を意味していることを確認してください)。

ただし、C++ ではそうではありません。オーバーロードされたメソッドは、署名が同じかどうか (異なる量、異なる型) に関係なく、同様にオーバーライドされます。つまり、明らかに、サブクラス オブジェクトの外部から呼び出された場合、基本クラスのメソッドはサブクラスで使用できなくなりました。

したがって、答えは、Java use overloadingについて話すときです。他の言語では、C++ で起こるように異なる場合があります

于 2012-02-24T12:52:30.790 に答える
1

ポリモーフィズムは、その意味に関する限り、より可能性が高くなります...Javaでオーバーライドする

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

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

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

しかし、引数を変更すると...動作が変更されます...

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

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

于 2012-09-11T14:04:44.593 に答える
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());

    }
}
于 2015-07-16T13:11:24.960 に答える
0

ポリモーフィズムは、単一のインターフェースを使用して異なるオブジェクトを一様に処理する言語の能力に関連しています。そのため、オーバーライドに関連しているため、インターフェース(または基本クラス)は多態的であり、実装者はオーバーライドするオブジェクトです(同じメダルの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.. のみが出力されます。

于 2008-09-30T19:50:18.837 に答える