728x90
Any 에는 다음과 같이 잘 설정된 규약들을 가진 메서드들이 있다
- equals
- hashCode
- toString
동등성
코틀린에는 두 가지 종류의 동등성이 있습니다.
- 구조적 동등성: equals 메서드와 이를 기반으로 만들어진 == 연산자(!= 포함)로 확인하는 동등성
- a 가 nullable 이 아니라면 a == b 는 a.equals(b)로 변환되고 a 가 nullalbe 이라면 a?.equals(b) ?: (b === null) 로 변환
- 레퍼런스적 동등성: ===, !== 연산자로 확인하는 동등성
- 두 피연산자가 같은 객체를 가리키면, true 를 리턴합니다.
data class Person(val name: String, val age: Int) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || javaClass != other.javaClass) return false
other as Person
return name == other.name && age == other.age
}
override fun hashCode(): Int {
return Objects.hash(name, age)
}
}
fun main() {
val person1 = Person("John", 25)
val person2 = Person("John", 25)
val person3 = person1
println(person1 == person2) // true (구조적 동등성)
println(person1 === person2) // false (레퍼런스 동등성)
println(person1 === person3) // true (레퍼런스 동등성)
}
- equals 메서드의 규약: equals 메서드는 다음의 다섯 가지 조건을 충족해야 합니다.
- 반사성: 객체는 자기 자신과 같아야 합니다. a.equals(a)는 항상 true입니다.
- 대칭성: 두 객체가 서로를 향해 같다고 주장해야 합니다. a.equals(b)가 true이면 b.equals(a)도 true입니다.
- 추이성: 하나의 객체가 두 번째 객체와 같고, 두 번째 객체가 세 번째 객체와 같다면, 첫 번째 객체는 세 번째 객체와도 같아야 합니다. 즉, a.equals(b)가 true이고 b.equals(c)가 true이면 a.equals(c)도 true입니다.
- 일관성: 비교 결과는 객체의 상태가 변하지 않는 한 일관되게 유지되어야 합니다. 즉, 여러 번 호출해도 항상 같은 결과를 반환해야 합니다.
- null-아님: 어떤 객체도 null과 같지 않습니다. a.equals(null)은 항상 false입니다.
- equals 메서드 구현 시 주의사항:
- 올바른 타입 확인: 비교하려는 객체의 타입을 확인하고, 잘못된 타입이면 false를 반환합니다.
- null 검사: 비교 대상 객체가 null인지 확인하고, null이면 false를 반환합니다.
- 중요한 필드 비교: 객체의 중요한 필드를 비교하여 동등성을 판단합니다.
- hashCode와의 연관성:
- equals 메서드를 재정의할 때는 hashCode 메서드도 반드시 재정의해야 합니다. 그렇지 않으면 해시 기반 컬렉션(e.g., HashMap, HashSet)에서 일관된 동작을 보장할 수 없습니다.
- equals가 true인 두 객체는 동일한 hashCode를 반환해야 합니다.
재밌는건 책에나와있듯이(URL과 관련된 equals 문제) equals 를 정의할때 동등성이 무언가에 의존한다면 상황에 따라 달라질 수 있기에 조심해야 할듯 하다.
특별한 이유가 없는 이상, equals 를 직접 구현하지 않는것이 좋다.
(상송을 지원하면서도 완벽한 사용자 정의 equals 함수를 만드는 것은 거의 불가능에 가깝다.)
728x90
'공부 > 이펙티브코틀린' 카테고리의 다른 글
아이템 42 - compareTo 의 규약을 지켜라 (0) | 2024.08.10 |
---|---|
아이템 41 - hashCode 의 규약을 지켜라 (0) | 2024.08.01 |
아이템39 - 태그 클래스보다는 클래스 계층을 사용하라 (0) | 2024.08.01 |
아이템 38 - 연산 또는 액션을 전달할 때는 인터페이스 대신 함수 타입을 사용하라 (0) | 2024.08.01 |
아이템 37 - 데이터 집합 표현에 data 한정자를 사용하라 (1) | 2024.07.14 |
댓글