Study/Java
equals 메소드를 오버라이딩 할 때는 보편적 계약을 따르자
유쾌한순례자
2010. 11. 11. 23:52
어렵게 꼬아놔서 뭔 소리인지 잘 몰랐는데 그냥 요약된 부분만 보니깐 알겠더라..
한마디로 수학 으로 생각하면 된다.
재귀적 : a=a
대칭적 : a=b b=a
이행적 : a=b b=c a=c
일관적 : a=b 같은 상태에서 a와 b의 값이 변함이 없다면 항상 a=b
개인적으로 자주 겪었던 대칭적 부분만 일단 자세히 짚어보았다.
equals 오버라이딩 공부할때 작성했던 소스를 책 예제로 약간 개조해보자면
이렇게 한다음 q1,q2를 이런식으로 선언했다.
Quiz q1 = new Quiz("asd");
String q2 = "Asd"
그 다음 q1.equals(q2) 결과와 q2.equals(q1)의 결과를 비교했다.
첫번째는 같다. 두번째는 다르다 가 나왔다.
a=b b=a 라는 대칭적 계약의 위반이다. Quiz의 equals 메소드는 일반 문자열을 처리하고 있는 반면 String equals 메소드는
대소문자를 구분하지 않는 문자열을 인식하지 못하는 것이다.
이것을 고쳐보자면
@Override
public boolean equals(Object obj) {
return obj instanceof Quiz && ((Quiz)obj).answer.equalsIgnoreCase(answer);
}
두 조건다 false 를 반환하게 된다.
이 예제의 의미를 잘 몰라서 자초스 뉴와이 님의 도움으로 알게 되었다.
뉴와이 님의 답변 전문
한마디로 수학 으로 생각하면 된다.
재귀적 : a=a
대칭적 : a=b b=a
이행적 : a=b b=c a=c
일관적 : a=b 같은 상태에서 a와 b의 값이 변함이 없다면 항상 a=b
개인적으로 자주 겪었던 대칭적 부분만 일단 자세히 짚어보았다.
equals 오버라이딩 공부할때 작성했던 소스를 책 예제로 약간 개조해보자면
@Override
public boolean equals(Object obj) {
if((obj instanceof Quiz)&& obj != null ) {
return answer.equalsIgnoreCase(((Quiz)obj).answer);
}
if((obj instanceof String) && obj != null){
return answer.equalsIgnoreCase((String)obj);
}
return false;
}
public boolean equals(Object obj) {
if((obj instanceof Quiz)&& obj != null ) {
return answer.equalsIgnoreCase(((Quiz)obj).answer);
}
if((obj instanceof String) && obj != null){
return answer.equalsIgnoreCase((String)obj);
}
return false;
}
이렇게 한다음 q1,q2를 이런식으로 선언했다.
Quiz q1 = new Quiz("asd");
String q2 = "Asd"
그 다음 q1.equals(q2) 결과와 q2.equals(q1)의 결과를 비교했다.
첫번째는 같다. 두번째는 다르다 가 나왔다.
a=b b=a 라는 대칭적 계약의 위반이다. Quiz의 equals 메소드는 일반 문자열을 처리하고 있는 반면 String equals 메소드는
대소문자를 구분하지 않는 문자열을 인식하지 못하는 것이다.
이것을 고쳐보자면
@Override
public boolean equals(Object obj) {
return obj instanceof Quiz && ((Quiz)obj).answer.equalsIgnoreCase(answer);
}
두 조건다 false 를 반환하게 된다.
이 예제의 의미를 잘 몰라서 자초스 뉴와이 님의 도움으로 알게 되었다.
뉴와이 님의 답변 전문
책 내용대로 라도 false false를 반환하게 설계하라고 추천하고 있는겁니다.
책에서 equlas()의 대칭성을 설명하는 부분이었고,
이전의 CaseInsensitiveString클레스에서
String클레스 형의 객체와 비교 가능하게 설계되어있을 겁니다.
하지만 String클레스에서 CaseInsensitiveString형의 비교 불가능하게 되어있죠..
ex)
CaseInsensitiveString a = new CaseInsensitiveString("Polish");
String b = "polish";
a.equals(b); //true
b.equals(a); //false
여서 대칭성의 문제로
CaseInsensitiveString에서
String형의 객체와의 비교처리를 지원하지 말라고 추천하는 내용입니다.
a에서의 equlas()만 지원하는 일방적인 equals 형태이죠.
이걸 방지하자는 내용이죠...