[Swift] Equatable, Hashable
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을-왜-상속해야-하는지-설명하시오