(Java) 추가 값 요소의 클래스를 계승하는 equals () 실현 방법

11061 단어 Java

개시하다


만약 상기 상속관계의 유형인 equals() 방법만 일반적으로 실시한다면 equals()는 만족해야 할 성질을 만족시킬 수 없다.이것은 모두가 다 알고 있는 것이다(보충1)
이 참고 문헌에도 회피 전략이 기재되어 있다.별문헌.를 참고하십시오.
*1 참조

결론


다음 2 매개변수의 equals() 정적 방법을 작성하여 Object를 통과합니다.equals()를 호출합니다.중요한 것은 두 종류의 equals () 부분을 호출하는 것이다.이것은 이 종류 이외에도 사용할 수 있다(보충2)
참고로 표준 API에는 Objects가 있습니다.equals(Object, Object)가 있지만 왼쪽 equals()만 호출됩니다.
ObjectUtil.java
final class ObjectUtil {
    private ObjectUtil() { throw new AssertionError("Not intended to be instanciated"); }
    public static boolean equals(final Object lhs, final Object rhs) {
        // 左辺・右辺の参照先が同じなら同一
        if (lhs == rhs) return true;
        // 左辺・右辺の参照先が共にnullなら同一
        if (lhs == null && rhs == null) return true;
        // 左辺・右辺の参照先のどちらかがnullなら不同
        if (lhs == null || rhs == null) return false;
        // 左辺・右辺の参照先が同一クラスならそのクラスのequals()を返却する
        if (lhs.getClass() == rhs.getClass()) return lhs.equals(rhs);
        // 左辺・右辺の参照先が別のクラスなら両クラスのequals()のandを返却する
        return lhs.equals(rhs) && rhs.equals(lhs);
    }
}

보충1

// 1. 対称性が満たせない
// -> 右辺・左辺を入れ替えると結果が異なる
// 上図のクラス構成を用いた例
Point1D p1 = new Point1D(0);
Point2D p2 = new Point2D(0, 0);
assert(p1.equals(p2) == true);  // x値しか比較しないためtrue
assert(p2.equals(p1) == false); // Point2Dのinstanceであることを判定するためfalse

// 2. 推移性が満たせない
// -> p1 == p2 && p2 == p3 の場合でも、p1 == p3 とならない
// 上図のクラス構成を用いた例
// 前提: Point2D.equals() 仕様に下記を追加しておく
//   引数が、Point1Dまたはそのサブクラス、かつx値が同じ場合でも、true
Point2D p1 = new Point2D(0, 0);
Point1D p2 = new Point1D(0);
Point2D p3 = new Point2D(0, 1);
assert(p1.equals(p2) == true); // 新仕様のためtrue
assert(p2.equals(p3) == true); // x値の比較しないためtrue
assert(p1.equals(p3) == false); // x,y値を比較するためfalse

// 3. リスコフの置換原則が満たせない
// -> サブクラスでも同様の動きが想定されるが、そうならない
// 上図のクラス構成を用いた例
// 前提1: Point1D.equals() 仕様を下記のように変更する
//   引数が、Point1D、かつx値が同じ場合のみ、true
// 前提2: CountingPoint1D.equals() 仕様を下記のように変更する
//   引数が、CountingPoint1D、かつx値が同じ場合のみ、true
Point1D p1 = new Point(0);
CountingPoint1D cp1 = new CountingPoint(0);
CountingPoint1D cp2 = new CountingPoint(0);
List<CountingPoint1D> list = Arrays.asList(cp1);
assert(list.contains(cp2) == true); // cp1 == cp2 のためtrue
assert(list.contains(p1) == false); // 前提1のためfalse

보충2

// 継承ではなくコンポジションを用いる
// 例
class Point2D {
    private final Point1D p1;
    private final int y;
    ...
    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Point2D)) return false;
        Point2D rhs = (Point2D)o;
        return p1.equals(rhs.p1) && y.equals(rhs.y);
    }
}
*1
조시르 부크(평성 26년)'Effective Java 제2판'완선.프로젝트 8
*2
안드레 알렉산더(2013)'프로그래밍 언어 D'수영회사.6.8.3

좋은 웹페이지 즐겨찾기