Hashable

protocol
해시로 사용할 수 있는 타입. Hasher로 integer hash 값을 생성한다.


Declaration

protocol Hashable

Overview

Hashable protocol을 준수한다면 Set 혹은 Dictionary key로 모든 타입을 사용할 수 있다.
String, integer, floating-point, boolean은 기본적으로 Hashable protocol을 준수하고 있다.

커스텀 타입도 해시 가능하다.
연관된 값 없이 enum을 정의하면, 자동적으로 Hashable을 준수한다.
그리고 커스텀 타입에다가 직접 hash(into:)를 구현하여 Hashable를 따르게 할 수 있다.

Conforming to the Hashable Protocol

Hashable protocol은 Equatable protocol을 상속받는다.

커스텀 Hashable 타입을 만들려면 아래의 조건들을 만족해야한다.

  • 구조체: 저장 property들은 Hashable을 준수해야한다.
  • enum : 관련된 값들은 모두 Hashable을 준수해야한다. (An enum without associated values has Hashable conformance even without the declaration.)

만약 위 조건들을 만족하지 못하거나, Hashable을 준수하게 확장하고 싶으면 hash(into:) 메소드를 구현해야한다.

struct GridPoint {
	var x: Int
	var y: Int
}

extension GridPoint: Hashable {
	static func == (lhs: GridPoint, rhs: GridPoint) -> Bool {
		return lhs.x == rhs.x && lhs.y == rhs.y
	}

func hash(into hasher: inout Hasher) {
	hasher.combine(x)
	hasher.combine(y)
}
  • hash(into:) 구현부에서 필수 구성요소들로 Hasher의 combine(_:)을 호출해야한다.
  • Hashable, Equatable protocol의 요구사항을 만족하는지 확실하게 하기 위해, Equatable conformance(적합성)을 커스텀화 하면 좋다. (== 함수)
var tappedPoints: Set 	= [GridPoint(x: 2, y: 3), GridPoint(x: 4, y: 1)]
let nextTap 		= GridPoint(x: 0, y: 1)

if tappedPoints.contains(nextTap) {
	print("Already tapped at (\(nextTap.x), \(nextTap.y)).")
} else {
	tappedPoints.insert(nextTap)
	print("New tap detected at (\(nextTap.x), \(nextTap.y)).")
}

// Prints "New tap detected at (0, 1).")

Topic

Providing a Hash Value

  1. func hash(into: inout Hasher)
    • 이 값의 필수 구성요소를 제공된 Hasher를 통해 해시함.
    • hasher의 finalize()를 절대로 호출해서는 안됨. complie-time error 발생할 수 있음.

Tags:

Categories:

Updated:

Leave a comment