11

最近、興味深い行動に出くわしました。.equals() をオーバーライドして Object 以外のパラメーターを取ると、呼び出されないようです。なぜこれが起こっているのか誰にも説明できますか?OOP のポリモーフィズムに関する私の理解に違反しているようですが、何かが足りないのかもしれません。

私が見ているものを示すはるかに単純なコードを次に示します。

public class MyClass {
  private int x;
  public MyClass(int n) { x = n; }
  public boolean equals(Object o) { return false; }
  public boolean equals(MyClass mc) { return x == mc.x; }
  public static void main(String[] args) {
    List<MyClass> list = new ArrayList<MyClass>();
    list.add(new MyClass(3));
    System.out.println("Contains 3? " + list.contains(new MyClass(3)));
  }
}

これを実行すると、" Contains 3? false" が出力されます。equals(Object) 関数が呼び出されたように見えますが、機能する別の関数があります。対照的に、次のように equals を記述すると、コードは期待どおりに機能します。

public boolean equals(Object o) {
  if(!(o instanceof MyClass))
    return false;
  MyClass mc = (MyClass)o;
  return x == mc.x;
}

パラメーターの型に基づいて、関数のどのバージョンを呼び出すかを判断しないのはなぜですか?

4

7 に答える 7

24

あなたは「オーバーライド」と「オーバーロード」を混同しています。

オーバーライド-ポリモーフィズムの目的で既存のメソッドの置換定義を追加します。メソッドは同じ署名を持っている必要があります。シグニチャは、名前と引数のタイプで構成されます。オーバーライドされるメソッドは、ターゲットオブジェクトの実行時タイプに基づいて実行時に選択されます。

オーバーロード-同じ名前で署名が異なるメソッドを追加します。オーバーロードされたメソッドは、ターゲットオブジェクトのコンパイル時のタイプに基づいてコンパイル時に選択されます。

于 2008-11-21T19:41:23.883 に答える
12

equals(Object)はスーパーメソッドをオーバーライドしています。まったく同じシグニチャを使用せずにスーパーメソッドをオーバーライドすることはできません(共変リターンタイプや例外などの例外がいくつかあります)。

于 2008-11-21T19:35:57.013 に答える
6

呼び出しているメソッドは、ArrayList の javadoc で次のように定義されていることに注意してください<E

boolean contains(Object o)
    Returns true if this list contains the specified element. 

それ以外の

boolean contains(E o)
    Returns true if this list contains the specified element. 

ArrayList.java の実装:

private transient Object elementData[];

public boolean contains(Object elem) {
    return indexOf(elem) >= 0;
}

public int indexOf(Object elem) {
    if (elem == null) {
        for (int i = 0; i < size; i++)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = 0; i < size; i++)
            if (elem.equals(elementData[i]))
                return i;
    }
    return -1;
}

<Eequals メソッドは ArrayList > の実装でオーバーライドされないため、Object スーパークラスで定義された equals メソッドを使用します。

Java で Object equals をオーバーライドする場合は、Object の hashCode メソッドもオーバーライドする必要があります。

とにかく、次のコードを試してみてください。

class A{    
    public int content;    
    A(){
        this(0);
    }    
    A(int value){
        content = value;
    }   
    public boolean equals(Object obj){
        System.out.println("overriding equals method");
        return this.content == ((A) obj).content;
    }    
    public boolean equals(A a){
        System.out.println("overloading equals method");
        return this.content == a.content;
    }    
    public static void main(String[] args){
        A x = new A(1);
        A y = new A(2);
        Object z  = new A(1);
        System.out.println(x.equals(y));
        System.out.println(x.equals(x));
        System.out.println(x.equals(z));
        //override as z is declared as Object at compile time
        //so it will use methods in class Object instead of class A
        System.out.println(x.equals((Object) y));
        System.out.println(x.equals((Object) x));        
    }   
}
//rant: they didn't teach me these in javaschool and I had to learn it the hard way.
于 2008-11-21T20:55:25.043 に答える
3

http://en.wikipedia.org/wiki/Polymorphism_(computer_science)にはさまざまな種類があります。javaはhttp://en.wikipedia.org/wiki/Double_dispatchを実行しません。

于 2008-11-21T19:44:06.123 に答える
2

contains(Object)メソッドのArrayList実装は、内部でObject.equals(Object)メソッドを使用するようにバインドされているため、equals(MyClass)メソッドのオーバーロードについては認識されません。(署名が一致する)オーバーライドメソッドのみが見つかります。

于 2008-11-21T19:47:32.203 に答える
-1

言い換えさせてください。

(1)コンパイラがジェネリックスに関するすべての情報を削除するため(消去、ここを参照)、(2)まったく同じシグネチャ(equals(Object))がないとメソッドをオーバーライドできないため、(3)実行時にすべてのオブジェクトがリストは、MyClassのインスタンスとしてではなく、オブジェクトとして扱われます。したがって、呼び出されるメソッドはequals(Object)です。これは、クラスによって上書きされるメソッドだからです。

于 2008-11-21T19:39:26.883 に答える
-1

contains()のメソッドがList実行時にオブジェクトの型を認識 していると想定していますが、これは正しくありません。

消去のため、は実行時にList<MyClass>単なるレギュラーになるため、メソッドはそのパラメーターを として認識し、実行時に定義したオブジェクトの代わりにオブジェクトを呼び出します。Listcontains()Objectequals()MyClass

于 2008-11-21T19:53:26.417 に答える