본문 바로가기

Swift 공부

Hashable , Equatable , Identifiable

https://developer.apple.com/documentation/swift/hashable

 

Apple Developer Documentation

 

developer.apple.com

Hashable

Hashable을 알기전 해쉬값 (Hash Value)을 알아야한다

그래서 해쉬값이란?

-> 데이터를 간단한 숫자로 변환한 것

자세히 설명하면 : 원본 데이터를 해쉬 함수 (hash function)을 사용하여 64bit의 Int값으로 변환한 것이다.

 

public protocol Hashable : Equatable {

*// Hashable Protocol의 정의*

var hashValue: Int { get }
    func hash(into hasher: inout Hasher)
}

 

그렇다면 Hashable 은 뭔가 해쉬가 가능하다~ 이런 뜻 같은데 어디에 사용하냐?

 

Hashable 한 타입 / 해쉬값은 어디에 사용할까?

Swift에서 Set 타입의 값, Dictionary 타입의 Key은 Hashable 해야 한다.

또한 Swift의 기본 타입인 String, Int 등은 자동으로 Hashable 하다.

열거형 (Enum)이 연관값 (associated value)을 가지지 않으면, 자동으로 Hashable 하다.

예를 들면 Set의 값에 String 타입을 담을 수 있다. 그리고 사용자 정의 타입을 Hashable 하도록 설정하면, Set의 값에 해당 타입을 담을 수 있다.

 

그래서 해쉬값은 왜 사용하는데? 이유는 값을 검색할때 검색의 속도가 빠르다  (해쉬 테이블을 따로 추가적인 공부가 필요하다.)

해쉬값을 사용하면 간단하게 배열을 에서 특정값을 찾을때 0번부터 ~ 마지막 인덱스까지 하나씩 돌아가면서 찾아야하는데

(알고리즘 책에서 본내용인데 이런 경우를 시간복잡도가 O(n)이라 한다)

해쉬 테이블은 해쉬값을 index로 사용해서 내가 원하는 값을 한번에 찾을 수 있다.

(이런 경우는 시간복잡도는 O(1) )

O(n) , O(1) 을 간단하게 설명하자면 O 안에 들어가는 n이 값이 늘어날때마다 경우의 수가 몇개씩 늘어나는지? 를 보는 거라고 보면된다

O(n) -> 1~10 까지 배열은 총 10번을 찾아야고 1 ~ 11 까지의 배열은 총 11번 들러야 모든 경우의 수를 찾을 수 있다.

값이 늘어남에따라 1씩 늘어나기에 O(n)

반면 O(1) 은 값이 아무리 늘어나도 해시값을 기반으로 데이터를 찾기에 "한번에" 원하는 값을 찾는다 그래서 O(1) 이다.

 

 

https://developer.apple.com/documentation/swift/equatable

 

Apple Developer Documentation

 

developer.apple.com

Equatable

눈썰미가 좋은 사람은 Hashable에 Equatable이 선언되어 있는것을 발견할 수 있을 것이다.

Equatable은 한줄로 설명하면 값이 같은지 비교할 수 있는 형식입니다.

if “안녕” == “안녕”{

print(”실행”)

}else{

print(”미실행”)

}

 

 

여기서 == 을 정의 하는게 Equatable 이라고 이해하면 편할 것 이다.

 

class ATEST {
 
    
  
    var A : String = "2"
    var B : String = "2"
   
    
}


var a : ATEST = ATEST()
var b : ATEST = ATEST()


if(a == b){
    print("같음")
}else{
    print("다름")
}

이렇게 만든다고하면 

 

이런 오류를 볼 수 있다. 왜? == 의 조건이 무엇이라고 할 것 이냐 변수 A가 같을경우? B가 같을경우? A, B 둘다 같을경우? 우리가 정해주지 않는이상 알 수 가없다.

그래서 이것을 정의해주는데 Equatable 이다.

 

class ATEST : Equatable{
    static func == (lhs: ATEST, rhs: ATEST) -> Bool {
        lhs.A == rhs.A && lhs.B == rhs.B
    }
    
    
  
    var A : String = "2"
    var B : String
    
    init(B : String){
        self.B = B
    }
    
}


var a : ATEST = ATEST(C : "2")
var b : ATEST = ATEST(C : "3")


if(a == b){
    print("같음")
}else{
    print("다름")
}

이 결과의 값은 무엇일까? 

상단의 함수를 보면 lhs , rhs 두개의 값이 있는데 이해하기 쉽게 lhs가 왼쪽값 rhs가 오른쪽에 있는값 이라고 생각하면 편할 것 이다.

그럼 함수를 풀이해보면 a,b 가 "동시"에 같아야 True를 리턴한다

그렇다면 위 함수의 값은 무엇일까? 답은 바로~~~ "다름" 이다.

 

Equatable 의 설명은 이 정도면 충분할 것 같다

 

근데 여기서 궁금점이 하나 생긴게 옵셔널한 값은 어떻게 비교를 할까?

 

class ATEST : Equatable{
    static func == (lhs: ATEST, rhs: ATEST) -> Bool {
        lhs.A == rhs.A && lhs.B == rhs.B && lhs.C == rhs.C
    }
    
    
  
    var A : String = "2"
    var B : String = "2"
    var C : String
    
    init(C : String){
        self.C = C
    }
    
}


var a : ATEST = ATEST(C : "3")
var b : ATEST? = ATEST(C : "3")


if(a == b){
    print("같음")
}else{
    print("다름")
}

 과연 이 값은 어떻게 나올까? 일반 클래스 와 옵셔널한 클래스의 값을 비교하면 놀랍게도 true가 나온다 이건 == 의 함수를 보면 알 수 있는데 

https://github.com/apple/swift/blob/main/stdlib/public/core/Optional.swift

 

GitHub - apple/swift: The Swift Programming Language

The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.

github.com

일반값에 옵셔널의 추가하여 비교를 한다고 한다 놀랍당.. 이건 몰랐따...

 

 

 

Identifiable

단순한 id 프로퍼티를 가지고 있고

struct , class 를 만들때 id값이 필요한 경우 사용 swiftUI에서 “List에서 id를 자동으로 채택 시켜준다.”

 

public protocol Identifiable {

    /// A type representing the stable identity of the entity associated with
    /// an instance.
    associatedtype ID : Hashable

    /// The stable identity of the entity associated with this instance.
    var id: Self.ID { get }
}

 

그럼 RxDataSource를 쓰는 내가 궁금한게 하나 생기는데 IdentifiableType 값은 지금까지 아이템의 고유값을 준다고 생각을 했는데

이번 기회에 찾아보면

 

public protocol IdentifiableType {
    associatedtype Identity: Hashable

    var identity : Identity { get }
}

Identity 는 Hashable한 값을 준수하면 된다. Hashable은 위에 설명 했으니 패스 

 

identity 에 Hashable한 값을 가지고 있으면 된다 이건데 어디에 쓰냐...?

 

import Foundation

public protocol AnimatableSectionModelType
    : SectionModelType
    , IdentifiableType where Item: IdentifiableType, Item: Equatable {
}

RxDataSorurce에서 AnimatableSectionModelType 을 채택하기위해 사용하는데

찾아본 바로 IdentifiableType 은 고유값을 위해 사용한다고한다. 

그럼 왜 Identifiable을 안쓰고 굳이? RxDataSource에서 만든걸 사용할까? (생각하건데 Identifiable이 iOS 13에 나왔고 그 이전에 사용하던 값이기에 따로 있는것 같다 아니라면 알려주세요 ㅜㅜ)