Hashable 프로토콜

썹스·2022년 12월 20일
0

Swift 문법

목록 보기
65/68

Hash / HashValue / Hashable

Hash: 어떠한 데이터를 고정된 길이와 유일한 값으로 반환 및 매핑해주는 함수, 코드, 체크섬 등을 의미합니다.

HashValue: Hash에 의해 도출되는 값을 의미합니다.

Hashable: 값의 고정된 길이와 유일성을 보장해주는 프로토콜입니다.


Hashable 프로토콜

Swift에서 Hashable 프로토콜은 값의 고정된 길이와 유일성을 보장하기 위해 만들어진 프로토콜입니다.

  • Hashable 프로토콜은 Equatable 프로토콜을 상속받기 때문에 Equatable 프로토콜의 요구사항 코드를 작성할 필요가 있습니다. (속성이 Equatable 프로토콜을 채택한 타입이라면 작성할 필요가 없지만, 클래스의 경우에는 꼭 작성해야 합니다.)

  • Comparable 프로토콜의 요구사항 코드는 아래와 같습니다.

func hash(into hasher: inout Hasher){
	hasher.combine(파라미터 이름)
    ...
}

Swift에서 기본적으로 제공해주는 기본타입(Int, String, Double 등)은 Hashable 프로토콜을 자동으로 채택하고 있습니다. 때문에 고유값(유일값)을 요구하는 Set, Dictionary의 key값으로 사용할 수 있습니다.

var set1: Set = [1,2,3,4]
var set2: Set = ["A","B","C","D"]

var dic1: Dictionary<Int, String> = [1:"A", 2:"B", 3:"C"]  // <key, value>
var dic2: Dictionary<String, String> = ["일":"A", "이":"B", "삼":"C"]  // <key, value>

하지만 사용자가 정의한 타입 즉, 커스텀 타입(Enum, Struct, Class)의 경우에는 Hashable 프로토콜을 자동으로 채택하지 않음으로 필요에 따라 사용자가 직접 Hashable 프로토콜 채택 및 요구사항 메서드를 구현해야 합니다.


📌 열거형(enum)의 Hashable

원칙적으로 열거형의 경우에는 Hashable 프로토콜을 채택해야만 고정값과 고유값을 가질 수 있습니다.

하지만 열거형에 연관값이 없다면 열거형은 기본적으로 Equatable/Hashable하기 때문에 별다른 채택 없이 사용 가능합니다. (기본타입의 원시값만 있는 경우에도 별다른 채택 없이 사용 가능합니다.)

✅ 연관값이 없는 경우의 Hashable

enum number{
    case one
    case two
    case three
}

var set: Set = [number.one, number.two, number.three]

✅ 기본타입의 원시값이 있는 경우의 Hashable

원시값의 타입이 기본타입(Hashable 프로토콜을 채택한 타입)이라면 Hashable 프로토콜 채택 없이 사용할 수 있습니다.

enum number: Int{
    case one
    case two
    case three
}

var set: Set = [number.one, number.two, number.three]

✅ 기본타입의 연관값이 있는 경우의 Hashable

연관값의 타입이 기본타입(Hashable 프로토콜을 채택한 타입)이라면 Hashable 프로토콜만을 채택하여 사용할 수 있습니다 (요구사항 메서드를 작성할 필요가 없음)

enum number: Hashable{
    case one(Int)
    case two(String)
    case three(Double)
}

var set: Set = [number.one(1), number.two("이"), number.three(3.0)]

📌 구조체(struct)의 Hashable

구조체의 모든 저장속성이 Hashable 프로토콜을 채택한 타입이라면 Hash 메서드 구현 없이 바로 사용 가능합니다.

✅ 구조체의 Hashable

struct Man: Hashable{
    var name: String
    var age: Int
 
    func hello(){
        print("안녕")
    }
}

var kim = Man(name: "김철수", age: 25)
var shin = Man(name: "신짱구", age: 25)

var set: Set = [kim, shin]

📌 클래스(class)의 Hashable

클래스의 모든 저장 속성이 Hashable 프로토콜을 채택한 타입이더라도 Hash 메서드를 꼭 구현해야 하며, Hashable 프로토콜이 상속받고 있는 Equatable 프로토콜의 요구사항 메서드 또한 작성해야 합니다.

✅ 클래스의 Hashable

class Man{
    var name: String
    var age: Int
  
    init(name: String, age: Int){
        self.name = name
        self.age = age
    }
  
    func hello(){
        print("안녕")
    }
}

extension Man: Hashable{
    static func == (lhs: Man, rhs: Man) -> Bool {  // 필수 구현!!
        return (lhs.name == rhs.name) && (lhs.age == rhs.age)
    }
   
    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
        hasher.combine(age)
    }
}

var kim = Man(name: "김철수", age: 25)
var shin = Man(name: "신짱구", age: 25)

var set: Set = [kim, shin]
profile
응애 나 코린이(비트코인X 코딩O)

0개의 댓글