문서비공식 한국어 번역
GitHub문서

동일성

 이 페이지의 마지막 수정: 2024년 8월 4일 
 ...

Kotlin 에서, 동일성에는 두 가지 종류가 있습니다:

  • 구조적 동일성(==) - equals() 함수를 사용하여 비교합니다.
  • 참조적 동일성(===) - 두 레퍼런스가 서로 같은 오브젝트를 가리키는지 비교합니다.

구조적 동일성

구조적 동일성은 두 오브젝트가 같은 내용이나 구조를 가지는지 확인합니다. 구조적 동일성은 == 연산자와 그의 반전된 연산자인 !== 에 의해 이루어지며, 규약 상 a == b 같은 표현은 아래와 같이 번역됩니다:

1a?.equals(b) ?: (b === null)
2

만약 anull 이 아니면, equals(Any?) 함수를 호출합니다. 그렇지 않으면, bnull 과 참조적으로 동일한지 확인합니다:

1fun main() {
2    var a = "hello"
3    var b = "hello"
4    var c = null
5    var d = null
6    var e = d
7
8    println(a == b)
9    // true
10    println(a == c)
11    // false
12    println(c == e)
13    // true
14}
15

null 과의 명확한 비교를 진행할 때는 어떠한 최적화도 이루어지지 않음을 기억하세요. a == nulla === null 로 변환될 뿐입니다.

Kotlin 에서, equals() 함수는 모든 클래스가 Any 로부터 상속받는 함수입니다. 기본적으로, equals()참조적 동일성 판단 로직을 가집니다. 그러나, Kotlin 의 클래스들은 equals() 를 재정의하여 커스텀 동일성 판단 로직을 제공할 수 있으며 이 경우에는 구조적 동일성으로 판단하게 됩니다.

값 클래스(value class) 나 데이터 클래스(data class) 들은 Kotlin 에서 자동으로 equals() 함수를 재정의하는 두 개의 특별한 타입들입니다. 그것이 그들이 기본적으로 구조적 동일성 판단 로직을 가지는 이유입니다.

그러나, 데이터 클래스들은 그의 부모 클래스에서 equals() 함수가 final로 표기되어있을 경우 그 동작을 재정의하지 않습니다.

그 외의 클래스(data 수정자가 없는 클래스) 들은 equals() 를 자동으로 재정의하지 않으며, 참조적 동일성을 판단하는 Any 의 그것을 그대로 둡니다. 구조적 동일성 판단 로직을 구현하려면, 비-데이터 클래스들은 그들의 동일성 비교 로직을 equals() 함수를 재정의함으로서 제공해주어야 합니다.

그러기 위해서, equals(other: Any?): Boolean 함수를 재정의하세요:

1class Point(val x: Int, val y: Int) {
2    override fun equals(other: Any?): Boolean {
3        if (this === other) return true
4        if (other !is Point) return false
5
6        // Compares properties for structural equality
7        return this.x == other.x && this.y == other.y
8    }
9}
10

eqauls() 함수를 재정의할 때, 동일성과 해싱 사이의 일관성을 유지하고 이들의 올바른 동작을 보장하기 위해 hashCode() 함수도 같이 재정의해주어야 합니다.

같은 이름의 다른 시그니쳐를 가진 함수(equals(other: Foo) 같은 것)들은 ==!= 연산자의 동작에 영향을 주지 않습니다.

구조적 동일성은 Comparable<...> 인터페이스가 정의하는 것과는 아무런 관계가 없으며, 그러므로 커스텀 equals(Any?) 구현만이 연산자의 동작을 바꿀 수 있습니다.

참조적 동일성

참조적 동일성은 어떤 두 오브젝트의 메모리 주소가 완전히 일치하여 서로 같은 인스턴스인지 판단합니다.

참조적 동일성은 === 연산자와 그의 반전된 연산자인 !== 에 의해 이루어지며, a === bab 가 서로 같은 오브젝트를 가리킬 때 true 로 평가됩니다:

1fun main() {
2    var a = "Hello"
3    var b = a
4    var c = "world"
5    var d = "world"
6
7    println(a === b)
8    // true
9    println(a === c)
10    // false
11    println(c === d)
12    // true
13
14}
15

런타임에 원시적인 값들은(Int 같은), === 확인이 == 와 동일하게 동작합니다.

참조적 동일성은 Kotlin/JS 플랫폼에서 다르게 구현됩니다. 이것에 대한 더 자세한 사항은 Kotlin/JS 문서를 확인해보세요.

부동 소수점 수들의 동일성

만약 동일성 판단의 피연산자들이 Float 이거나 Double 이면, IEEE 754 부동 소수점 연산 표준의 판단을 따릅니다.

이 행동은 부동 소수점 수인 것으로 정적-타이핑되지 않는 피연산자들에 따라 다릅니다. 이러한 경우에는, 구조적 동일성이 구현됩니다. 결과적으로, 부동 소수점 수로 정적-타이핑되지 않은 피연산자들 사이의 비교는 IEEE 표준을 다릅니다. 이 시나리오에서:

  • NaN 은 그 자신과 같습니다.
  • NaNPOSITIVE_INFINITY 를 포함하여 다른 어떠한 값보다도 큽니다.
  • -0.00.0 과 다릅니다.

더 자세한 사항은 부동 소수점 수의 비교 문서를 확인해보세요.

배열의 동일성

두 배열이 서로 같은 요소들을 가지고 있는지 확인하려면, contentEquals() 를 사용합니다.

더 자세한 사항은, 배열의 비교 문서를 확인해보세요.

이 페이지가 도움이 되셨다면, 원문 페이지에 방문해 엄지척을 해주세요!