본문 바로가기
Swift

[Swift] Equatable, Hashable

by thoonk: 2023. 1. 3.

Equatable과 Hashable 프로토콜에 관해 기록합니다. 

Equatable

protocol Equatable {
    static func == (lhs: Self, rhs: Self) -> Bool
}

- 값이 동일한 지 비교할 수 있는 타입

- 이 프로토콜을 준수하는 타입은 == 혹은 !=를 사용하여 비교할 수 있음.

- 기본 데이터 타입 Int, String, Double 등 Hashable 프로토콜을 준수하고 있어 값을 비교할 수 있음.

Hashable

protocol Hashable: Equatable {
    var hashValue: Int { get }	
}

- 정수 hash 값을 제공하는 타입

- hash → 해시 함수에 의해 얻어지는 값 → 해시값, 해시코드, 해시 체크섬

- 해시 함수: 임의의 길이의 데이터를 고정된 길이의 데이터로 매핑하는 함수

- hashValue - 어떠한 데이터를 Hash 함수에 넣게 되면 반환해주는 값

- HashTable에서 hash값을 찾기 위한 key가 필요하고 Unique해야 함.

  → Unique한지 비교하기 위해 Hashable은 Equatable을 채택하고 있음.

Hashable 구현

1) Equatable 프로토콜 준수 (== 함수 구현) → HashValue가 Unique해야 함.

2) HashValue 생성

  • hashValue는 Hasher 구조체의 combine 메서드로 identifier를 넘겨 생성함.
  • Hashable protocol 함수 func hash(into hasher: inout Hasher)를 사용
func hash(into hasher: inout Hasher) {
    hasher.combine(identifier)
}

 

Hashable 프로토콜을 준수하는 모든 타입은 set, dictionary key로 사용

hash(into:) 메서드를 구현하여 Custom 타입에도 Hashable을 준수할 수 있음.

연관 값(associated value) 없이 enum을 정의하면 자동으로 Hashable을 준수함.

저장(Stored) 프로퍼티가 모두 Hashable한 구조체 또는 Hashable한 타입을 가지는 enum일 때, hash(into:) 메서드 자동으로 제공함.

 

구조체(Struct)의 경우, 프로퍼티들이 Hashable한 기본 자료형이므로 hash함수를 구현할 필요가 없음.

struct Test: Hashable {
    let subject: String
    let number: Int
}

// Hashable을 준수한 Test 구조체는 Dictionary의 Key로 사용할 수 있음.
let testCase = [Test: Int]()

 

클래스(Class)의 경우 Hashable을 준수하기 위해 hash함수를 구현해야 함.

class Test: Hashable {
    let subject: String
    let number: Int
    
    init(subject: String, number: Int) {
        self.subject = subject
        self.number = number
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(subject)
        hasher.combine(number)
    }
    
    // Equatable
    static func == (lhs: Test, rhs: Test) -> Bool {
        lhs.subject == rhs.subject && lhs.number == rhs.number
    }
}

// Hashable을 준수한 Test 클래스는 Dictionary의 Key로 사용할 수 있음.
let testCase = [Test: Int]()

 

열거형(Enum)의 경우 두가지로 나뉜다.

- 연관 값이 없는 열거형일 때 Hashable을 준수하지 않아도 자동으로 채택됨.

enum TestCase {
    case login
}

let testCase = [TestCase: Int]()

- 연관 값이 있는 열거형일 때 Hashable을 채택해야 함.

enum TestCase: Hashable {
    case login(id: String, password: String) 
}

let testCase = [TestCase: Int]()

 

부족한 점 피드백해주시면 감사합니다 :)

 

Ref.

https://velog.io/@hayeon/Hashable이-무엇이고-Equatable을-왜-상속해야-하는지-설명하시오

https://woongsios.tistory.com/145

'Swift' 카테고리의 다른 글

[Swift] @discardableResult  (2) 2021.07.18
[Swift] split vs components  (0) 2021.06.05
[Swift] Optional  (0) 2021.05.22
[Swift] ARC (1)  (0) 2021.05.12
[Swift] popLast() vs removeLast()  (0) 2021.05.11

댓글