인스턴스가보다 구체적인 유형의 다른 인스턴스와 동일 할 수 있습니까? Point3D(10, 20, 50); twoD.equals(threeD); // true threeD.equals(twoD);

이 기사를 읽었습니다 : Java에서 평등 메소드를 작성하는 방법 .

기본적으로 상속을 지원하는 equals () 메소드에 대한 솔루션을 제공합니다.

Point2D twoD   = new Point2D(10, 20);
Point3D threeD = new Point3D(10, 20, 50);
twoD.equals(threeD); // true
threeD.equals(twoD); // true

그러나 좋은 생각입니까? 이 두 인스턴스는 같지만 두 개의 다른 해시 코드를 가질 수 있습니다. 조금 틀리지 않습니까?

대신 피연산자를 캐스팅하면 더 나은 결과를 얻을 수 있다고 생각합니다.



답변

이것은 전이성 을 파괴하기 때문에 평등이되어서는 안됩니다 . 다음 두 가지 표현을 고려하십시오.

new Point3D(10, 20, 50).equals(new Point2D(10, 20)) // true
new Point2D(10, 20).equals(new Point3D(10, 20, 60)) // true

평등은 전이 적이므로 다음 표현도 참임을 의미해야합니다.

new Point3D(10, 20, 50).equals(new Point3D(10, 20, 60))

그러나 물론 아닙니다.

따라서 캐스팅에 대한 아이디어는 정확합니다. Java에서 캐스팅은 단순히 참조 유형을 캐스팅하는 것을 의미합니다. 여기서 실제로 원하는 것은 Point2D객체에서 새 객체를 만드는 변환 방법입니다 Point3D. 이것은 또한 표현을 더 의미있게 만듭니다.

twoD.equals(threeD.projectXY())


답변

Alan J. Perlis 의 지혜 에 관한 기사를 읽지 않겠습니다.

그림 9. 10 개의 데이터 구조에 대한 10 개의 함수보다 100 개의 함수가 하나의 데이터 구조에 대해 작동하는 것이 좋습니다.

“평등”을 얻는다는 것은 밤에 스칼라의 Martin Ordersky 발명가 를 유지시키는 일종의 문제라는 사실 equals은 상속 트리에서 재정의 가 좋은 아이디어 인지 여부를 잠시 멈추어야 한다는 것입니다.

우리가 불행한 경우에 발생하는 ColoredPoint일은 상속을 사용하여 데이터 유형을 향상시키지 않고 데이터 유형을 확산시키기 때문에 지오메트리가 실패한다는 것입니다. 이것은 상속 트리의 루트 노드로 돌아가서 작업을 수행해야 함에도 불구하고 equals. 왜 a z와 a color를 추가하지 Point않습니까?

좋은 이유는 것이라고 PointColoredPoint해당 도메인이 섞여 결코 적어도 경우 … 다른 도메인에서 작동합니다. 그러나이 경우에는를 재정의 할 필요가 없습니다 equals. 비교 ColoredPointPoint평등은 그들이 어울릴 수있는 세 번째 영역에서만 의미가 있습니다. 이 경우, 혼합되지 않은 도메인 중 하나 또는 다른 하나 또는 둘 다에서 동등성 시맨틱을 적용하려고 시도하는 것보다 “평등”을 해당 세 번째 도메인에 맞게 조정하는 것이 좋습니다. 다시 말해, “평등”은 6 개월 전에 오전 2시에 좋은 생각이라고 생각한 경우에도 ColoredPoint.equals(pt)인스턴스에서 실패 하기 를 원하지 않기 때문에 양쪽에서 진흙이 유입되는 장소에 대해 로컬로 정의해야합니다. .PointColoredPoint


답변

구 프로그래밍 신들이 클래스를 가진 객체 지향 프로그래밍을 발명 할 때, 객체에 대해 “is a”와 “has a”라는 두 가지 관계를 갖는 것이 구성과 상속에 관한 시점을 결정했습니다.
이것은 서브 클래스가 부모 클래스와 다른 문제를 부분적으로 해결했지만 코드를 손상시키지 않고 사용할 수있게했습니다. 서브 클래스 인스턴스는 “수퍼 클래스 객체”이고이를 직접 대체 할 수 있기 때문에 서브 클래스에 더 많은 멤버 함수 또는 데이터 멤버가 있더라도 “있다”는 부모의 모든 함수를 수행하고 모든 회원. 따라서 Point3D는 “is a”Point이고 Point2D는 둘 다 Point에서 상속하는 경우 “is”라고 말할 수 있습니다. 또한 Point3D는 Point2D의 하위 클래스가 될 수 있습니다.

클래스 간 평등은 도메인마다 문제가 있으며, 위의 예는 프로그래머가 프로그램이 올바르게 작동하는 데 필요한 것에 대해 모호합니다. 일반적으로 수학 영역 규칙을 따르고 비교 범위를이 경우 두 차원으로 제한하면 모든 데이터 멤버를 비교하지 않는 경우 데이터 값이 동일합니다.

따라서 평등이 좁아지는 표를 얻습니다.

Both objects have same values, limited to subset of shared members

Child classes can be equal to parent classes if parent and childs
data members are the same.

Both objects entire data members are the same.

Objects must have all same values and be similar classes. 

Objects must have all same values and be the same class type. 

Equality is determined by specific logical conditions in the domain.

Only Objects that both point to same instance are equal. 

일반적으로 문제 영역에서 필요한 모든 기능을 계속 수행 할 수있는 가장 엄격한 규칙을 선택합니다. 숫자에 대한 내장 평등 테스트는 수학 목적만큼 제한적으로 설계되었지만 반올림, 자르기, 자르기, gt, lt 등을 포함하여 목표가 아닌 경우 프로그래머는 여러 가지 방법을 사용할 수 있습니다. . 타임 스탬프가있는 객체는 생성 시간으로 비교되는 경우가 많으므로 각 인스턴스는 고유해야하므로 비교가 매우 구체화됩니다.

이 경우 설계 요소는 객체를 비교하는 효율적인 방법을 결정하는 것입니다. 때로는 모든 객체 데이터 멤버를 재귀 적으로 비교하는 것이 당신이해야 할 일이며 많은 데이터 멤버가있는 많은 객체가있는 경우 매우 비쌀 수 있습니다. 대안은 관련 데이터 값만 비교하거나, 객체가 다른 유사한 객체와의 빠른 비교를 위해 관련 데이터 멤버의 해시 값을 생성하도록하고, 더 빠르고 덜 CPU 집약적 인 비교를 수행하기 위해 콜렉션을 정렬하고 정리하는 것입니다. 컬링 할 데이터가 동일하고 단일 오브젝트에 대한 중복 포인터가 대신 배치됩니다.


답변

규칙은 재정의 할 때마다 hashcode()재정의 equals()되며 그 반대도 마찬가지입니다. 이것이 좋은 아이디어인지 아닌지는 의도 된 사용법에 달려 있습니다. 개인적으로 isLike()동일한 효과를 얻기 위해 다른 방법 ( 또는 유사한 방법 )을 사용합니다.


답변

비공개 클래스에 대해 동등성 테스트 방법을 사용하는 것이 유용 합니다. 동일한 유형의 객체가 동일한 정보를 나타내는 경우 서로 다른 유형의 객체가 서로 “동일한”것으로 간주 할 수 있지만 Java는 클래스가 각각을 가장 할 수있는 수단을 허용하지 않기 때문입니다. 다른 표현으로 다른 객체를 가질 수있는 경우에는 단일 공용 페이퍼 유형을 사용하는 것이 좋습니다.

예를 들어, 불변의 2 차원 행렬을 캡슐화하는 클래스를 생각해보십시오 double. 외부 방법 중 하나가 크기가 1000 인 항등 행렬을 요청하면 두 번째 방법은 대각선 행렬을 요청하고 1000을 포함하는 배열을 전달하고, 세 번째 방법은 2D 행렬을 요청하고 기본 대각선의 요소가 모두 1.0 인 1000×1000 배열을 전달합니다. 다른 모든 클래스가 0 인 경우, 세 클래스 모두에 주어진 객체는 내부적으로 서로 다른 백업 저장소를 사용할 수 있습니다 (첫 번째는 크기에 대한 단일 필드를 갖고, 두 번째는 1000 요소 배열을, 세 번째는 1000 요소 배열을 가짐). [3 개 모두 1000×1000 불변 매트릭스를 대각선에 1 개로 캡슐화하고 다른 곳에서는 0을 캡슐화하므로] 서로 동등한 것으로보고해야합니다.

별개의 백업 저장소 유형이 존재하지 않는다는 사실 외에도 래퍼는 비교를 용이하게하는 데 유용 할 것입니다. 항목의 동등성을 검사하는 것은 일반적으로 다단계 프로세스이기 때문입니다. 첫 번째 항목이 두 번째 항목과 같은지 알고 있는지 묻습니다. 모르는 경우 두 번째가 첫 번째와 같은지 알고 있는지 물어보십시오. 어떤 객체도 알지 못하면 각 배열에 개별 요소의 내용에 대해 문의하십시오 (장기 개별 항목 비교 경로를 수행하기로 결정하기 전에 다른 검사를 추가 할 수 있음).

이 시나리오에서 각 개체에 대한 동등성 검정 방법은 3 가지 상태 값 ( “예, 동등하지 않습니다”, “같지 않습니다”또는 “모름”)을 반환해야합니다. 따라서 일반적인 “같음”방법은 적합하지 않습니다. 다른 객체에 대해 물었을 때 어떤 객체도 단순히 “모름”이라고 대답 할 수 있지만, 예를 들어 메인 매트릭스 외부의 요소에 대해 아이덴티티 매트릭스 또는 대각선 매트릭스를 요구하지 않는 대각선 매트릭스에 로직을 추가하면 이러한 비교를 크게 촉진 할 수 있습니다. 유형.


답변