본문 바로가기

IOS Swift

Hashable 이란? - Swift

Hasable

정수 해쉬값을 제공하는 Hasher로 해쉬 될 수 있는 타입.  

 

해쉬란?

해시 함수에 의해 얻어지는 값은 해시 값, 해시 코드, 해시 체크섬 또는 간단하게 해시라고 한다. (위키백과)

이걸로 유추해보면 해시가 될 수 있다 라는 건 HashTable 에서 찾을 수 있다는 의미입니다. 
HashTable 에서 hash 값을 찾으려면 key가 필요하고 그 key는 식별할 수 있도록 unique 해야합니다.

음 그래서 Hashable을 채택하면 Set 나 Dictionary 타입의 Key 값이 될 수 있는 거군요.

위의 정의를 다시 설명해보자면 Hashable은 Hashtable의 Key 값이 될 수 있도록 해주는 프로토콜 입니다. 

그 과정에서 Hasher가 사용됩니다. 원래는 해쉬함수를 이용해서 해쉬 값을 구하는데 Swift 에서는 그 과정이 Hasher 객체 안에 들어있어서 Hasher에게 프로퍼티만 combine 해주면 해쉬 정수값을 제공해 줍니다. 

그런데 해쉬 정수값은 unique해야 한다고 했잖아요? 그래서 == 함수를 사용해서 같은지 비교합니다.

코드로 예를 들어보겠습니다.

var dic = ["key1":0, "key2":0]
dic["key1"]! += 1
dic["key2"]! += 1

print(dic) // ["key1":1, "key2": 1]

이렇게 되야 정상입니다. 하지만 만약 해쉬충돌이 일어나서

"key1" != "key2" 인데 key1.hashValue == key2.hashValue 가 된다면?

dic은 ["key1": 2] or ["key2": 2] 로 원하지 않는 결과로 이어집니다.

이처럼 == 함수의 역활은 중요합니다! 

 

언제 사용해?

  1. 구조체나 클래스로 객체를 만들었는데 얘내끼리 비교하고 싶을 때 Hashable protocol 사용 이건 Equatable로도 충분히가능한듯
  2. Set이나 Dictionary key값에 클래스나 구조체를 넣을 때 사용 (다른 Int, String, Bool 등 기본 자료형은 Hashable채택하고 있다.)

 

 

Hashable 구현

Hashable을 사용하기 위해선 다음 두가지가 필요하다.

  1. == :  hashValue는 고유한 값이여야 하기 때문에 고유값인지 식별해줄 수 있는 == 함수가 필요 (Equatable에 ==함수 존재)
  2. hashValue : Hashable 정의에서 나와있다시피 hasher가 해쉬값을 제공해줌

 

Swift 4.1 이후 구조체는 모든 프로퍼티가 (Hashable,Equatable)하면 자동합성으로 해당 프로토콜을 자동으로 준수(synthesized implementation) 한다. Comparableraw value를 가지고 있지 않은 열거형(enumerations)에 한해  synthesized implementation을 제공한다.

참고: https://github.com/apple/swift-evolution/blob/master/proposals/0185-synthesize-equatable-hashable.md#support-for-comparable

//For a struct, all its stored properties must conform to Hashable.
//모든 프로퍼티가 Hashable 하므로 synthesized implementation 제공 (==, hash()안써도됨)
struct StructHash: Hashable {
    var x = 0
    var y = 0
}

class ClassHash: Hashable {
    static func == (lhs: ClassHash, rhs: ClassHash) -> Bool {
        return lhs.x == rhs.x && lhs.y == rhs.y
        
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(x)
        hasher.combine(y)
    }
    
    var x = 0
    var y = 0
}

var dic = [StructHash:Int]()
var dic2 = [ClassHash:Int]()

 

 

요약

  1. Hashable은 Hasher가 해쉬값을 제공해주는 프로토콜이다.
  2. Equatable을 상속받고 있는 이유는 해쉬값을 생성하려면 key가 필요하고 그 key는 유니크해야하기 때문에 유니크한지 검사하기 위해 ==함수가 필요한데 ==함수를 사용하려면 Equatable을 채택해야 한다.

 

 

 

보너스 사전지식 

HashTable 자료 구조에 대해서 : https://hongz-developer.tistory.com/127

4.1 버전 이하의 Hashable 구현 코드가 궁금하다면? : https://hongz-developer.tistory.com/128

 

 

출처 및 참고

  1. Hashable 공식문서 : https://developer.apple.com/documentation/swift/hashable
  2. 삼쓰님 : https://woongsios.tistory.com/145
  3. 제드님 : https://zeddios.tistory.com/498
반응형

'IOS Swift' 카테고리의 다른 글

Hashable Swift 4.1 전 과 후  (2) 2021.08.29
[자료구조] HashTable 이란?  (0) 2021.08.29
Tuple이란? - Swift  (0) 2021.08.17
Frame과 Bounds의 차이  (4) 2021.08.03
Swift 네이밍 컨벤션  (0) 2020.12.09