3

Xptoという名前の抽象クラスと、 PersonおよびCarという名前のそれを拡張する 2 つのサブクラスがあります。また、main() を持つTestという名前のクラスと、2 人の人物または車 (または Xpto を拡張するクラスの任意のオブジェクト) が等しいかどうかを検証するメソッドfoo()があります。したがって、Person クラスと Car クラスの両方でequals()を再定義しました。2 人が同じ名前を持っていれば対等であり、2 台の車が同じ登録をしていれば対等です。

ただし、Test クラスで foo() を呼び出すと、常に「false」になります。理由は理解できます: equals() は Xpto 抽象クラスで再定義されていません。では、その foo() メソッドで 2 人の人物または車 (または Xpto を拡張するクラスの任意のオブジェクト) を比較するにはどうすればよいでしょうか?

要約すると、これは私が持っているコードです:

public  abstract class Xpto {


}

public class Person extends Xpto{

        protected String name;

        public Person(String name){
                this.name = name;
        }

        public boolean equals(Person p){
                System.out.println("Person equals()?");
                return this.name.compareTo(p.name) == 0 ? true : false;
        }
}

public class Car extends Xpto{
        protected String registration;

        public Car(String registration){
                this.registration = registration;
        }

        public boolean equals(Car car){
                System.out.println("Car equals()?");
                return this.registration.compareTo(car.registration) == 0 ? true : false;
        }
}

public class Teste {

        public static void foo(Xpto xpto1, Xpto xpto2){
                if(xpto1.equals(xpto2))
                        System.out.println("xpto1.equals(xpto2) -> true");
                else
                        System.out.println("xpto1.equals(xpto2) -> false");

        }

        public static void main(String argv[]){
                Car c1 = new Car("ABC");
                Car c2 = new Car("DEF");
                Person p1 = new Person("Manel");
                Person p2 = new Person("Manel");

                foo(p1,p2);
        }
}
4

9 に答える 9

4

他の人が言うように、オーバーライドするメソッドのシグネチャはまったく同じでなければなりません。メソッドをオーバーライドするときは、オーバーライドしていることを確認するために@Override、関数の上に注釈を使用してください。メソッドを変更すると、Eclipse などの IDE で警告が表示されます。

これは次のようになります。

@Override
public boolean equals(Object obj){
...Your code here...
}

hashCode()アイテムをリスト、セット、ハッシュテーブルなどに挿入するときに、等式 (およびパフォーマンス)hashCode()が使用されるため (時には使用されequals()ないこともあります!) 、オーバーライドすることをお勧めします。

したがって、最終的なコードは次のようになります。

@Override
public boolean equals(Object obj){
...Your code here...
}

@Override
public int hashCode(){
...Your code here...
}

javadocの詳細情報

于 2010-04-23T12:42:41.103 に答える
2

理由は理解できます: equals() は Xpto 抽象クラスで再定義されていません。

実際には、コードのどこequals()にも再定義されていません。それをオーバーライドするには、メソッドにパラメータ型を持たせる必要があり、それをキャストする必要があります ( 2 つの異なるサブクラスのインスタンスが比較されたときに戻るようにテストした後)。Objectinstanceoffalse

于 2010-04-23T12:32:58.187 に答える
1

Javadocには、パラメーターとしてオブジェクトを使用して equals メソッドをオーバーライドする必要があると記載されています。

他のオブジェクトがこのオブジェクトと「等しい」かどうかを示します。

したがって、サブクラス equals メソッドは次のようになります。

public class Car extends Xpto
{
    protected String registration;

    public Car(String registration)
    {
        this.registration = registration;
    }

    public boolean equals(Object obj)
    {
        if (obj == null)
        {
            return false;
        }
        if (obj == this)
        {
            return true;
        }
        if (!obj.getClass().isAssignableFrom(getClass()))
        {
            return false;
        }
        Car car = (Car) obj;
        return this.registration.compareTo(car.registration) == 0 ? true : false;
    }
}
于 2010-04-23T12:29:58.567 に答える
1

public boolean equals(Person p) または public boolean equals(Car p) を宣言しても、オブジェクトの public boolean equals(Object o) はオーバーライドされません。これは、決して呼び出されない新しいメソッドです。

于 2010-04-23T12:33:33.150 に答える
1

これが私がそれについて行く方法です:

public  abstract class Xpto {

}

public class Person extends Xpto{

    protected String name;

    public Person(String name){
            this.name = name;
    }

    public boolean equals(Object o){
       if(o == null || !getClass().equals(o.getClass())
          return false;
       Person p = (Person) o;
       System.out.println("Person equals()?");
       return this.name.compareTo(p.name) == 0 ? true : false;
    }
}

public class Car extends Xpto {
    protected String registration;

    public Car(String registration){
            this.registration = registration;
    }

    public boolean equals(Object o){
       if(o == null || !getClass().equals(o.getClass())
          return false;
       Car car = (Car) o;
       System.out.println("Car equals()?");
       return this.registration.compareTo(car.registration) == 0 ? true : false;
    }
}

public class Teste {

    public static void foo(Xpto xpto1, Xpto xpto2){
            if(xpto1.equals(xpto2))
                    System.out.println("xpto1.equals(xpto2) -> true");
            else
                    System.out.println("xpto1.equals(xpto2) -> false");

    }

    public static void main(String argv[]){
            Car c1 = new Car("ABC");
            Car c2 = new Car("DEF");
            Person p1 = new Person("Manel");
            Person p2 = new Person("Manel");

            foo(p1,p2);
    }
}

すべてのクラスequals(Object)は、クラスからメソッドを継承しObjectます。したがって、Xptoそのようなメソッドを定義する必要はありません。

Personサブクラス (つまり、 、 )でこのメソッドをオーバーライドCarする場合、まったく同じシグネチャで定義する必要があります。つまり、equalsメソッドのパラメーターは typeObjectである必要があり、メソッドの実装はそれをダウンキャストする必要があります。

于 2010-04-23T12:34:28.183 に答える
1

equals メソッドは次のようになります。

@Override public boolean equals(Object o) {
   if (!(o instanceof YourType)) {
      return false;
   }
   YourType yt = (YourType)o;
   ... // rest here
}

hashCodeまた、コレクションでタイプを適切に使用できるように、オーバーライドすることも忘れないでください。

于 2010-04-23T12:36:09.593 に答える
1

等しいコントラクトを完全に満たし、階層内の 2 つの異なるクラスを互いに同等にすることは、一般的に非常に困難/不可能であり、通常は行われません。通常、equals メソッドはクラスが同じかどうかをテストします (したがって、同じサブクラスの 2 つのインスタンスは互いに等しくなりますが、2 つの異なるサブクラスの 2 つのインスタンスは等しくなりません)。

ただし、プロパティが 1 つしかないため、Xpto で equals を実装することは可能です。これを行う明白な方法は、Xpto で抽象メソッドを定義してから、Xpto でも equals をオーバーライドすることです。

 public class Xpto {
        protected abstract String getIdentity();

        @Override
        public boolean equals(Object o) {
            if (o == null) return false;
            //Typical implementation
            //if (getClass() != o.getClass()) return false;
            if (!(o instanceof Xpto)) return false; //risky implementation, but will allow a car to compare to a person
             return getIdentity().equals((Xpto) o.getIdentity());
        }

        @Override
        public int hashCode() {
             return getIdentity().hashCode();
        }
  }

実装で equals を実際にオーバーライドしていないことを指摘する人もいます。将来的には、@Override アノテーションを使用することで、コンパイラに支援してもらうことができます。あなたの場合、コンパイルエラーが早く発生したため、時間を節約できました。

于 2010-04-23T12:42:36.347 に答える
0

equals()メソッドをオーバーライドするのではなく、オーバーロードします。署名をに変更します

public boolean equals(Object o)

次に o を Person/Car にキャストして比較します。

ところで、文字列を次のように比較することもできますequals()

return registration.equals(car.registration);
于 2010-04-23T12:36:55.317 に答える
0

あなたのサブクラスは、equals(Person) または equals(Car) を定義していますが、どちらも Xpto を渡されることを好みません。コレクションで動作するように、両方を equals(Xpto) または equals(Object) として宣言すると、問題は解決するはずです。

この方法で equals() メソッドを再宣言する場合、(1) 渡されたオブジェクトのクラスを確認する必要があることに注意してください。これは、それらが Cars または Persons であることを保証できないためです。(2)おそらく getHashCode() もオーバーライドしたくなるでしょう。特に、両方を equals(Object) にすることにした場合は、getHashCode() が等しい 2 つのオブジェクトに対して等しいハッシュ コードを返す必要があるためです。

于 2010-04-23T12:37:01.440 に答える