Danny의 iOS 컨닝페이퍼
article thumbnail

Equatable

Equatable은 비교를 할 수 있는 프로토콜입니다.

 

Equatable정의를 한 번 봅시다.

public protocol Equatable {

    /// Returns a Boolean value indicating whether two values are equal.
    ///
    /// Equality is the inverse of inequality. For any values `a` and `b`,
    /// `a == b` implies that `a != b` is `false`.
    ///
    /// - Parameters:
    ///   - lhs: A value to compare.
    ///   - rhs: Another value to compare.
    static func == (lhs: Self, rhs: Self) -> Bool
}

위와 같이 Equatable 프로토콜을 준수하는 타입은 등호 연산자 (==) 또는 같지 않음 연산자 (!=)를 사용하여 동등성을 비교할 수 있습니다.

 

Swift의 기본 데이터 타입은 Equatable 프로토콜을 따르고 있죠. (Int, Double, Float, Bool, String …)

 

이와 같이 서로 비교를 할 수 있죠.

let num1 = 10
let num2 = 10
 
num1 == num2            // true
 
let str1 = "Daniel"
let str2 = "Yang"
 
str1 == str2            // false

 

구조체, 열거형 또는 클래스와 같은 사용자 타입에서는 어떻게 될까요?

구조체부터 살펴보겠습니다.

struct Phone {
    var name: String
}

Phone(name: "iPhone") == Phone(name: "Zfilp")
// Error : Referencing operator function '==' on 'Equatable' requires that 'Phone' conform to 'Equatable'

비교를 하려면 Equatable을 준수해야 한다고 빨간 에러가 나오네요. 

 

자 그러면 컴파일러 말대로 Equatable 채택을 해봅시다.

struct Phone: Equatable {
    var name: String
}

Phone(name: "iPhone") == Phone(name: "Zfilp")
// false

에러도 사라지고 구조체에서도 서로 비교를 할 수 있게 됐습니다!

 

name의 타입은 String형이기 때문에 기본적으로 Equatable프로토콜이 채택되어 있어 비교가 가능한 것입니다.

 

참고로 여러 개의 프로퍼티가 있을 경우 해당 구조체나 클래스 내의 모든 프로퍼티가 같은 값을 가져야 결과 값으로 같음(true)이 나옵니다.

 

 

이제 클래스에서도 사용해 볼까요?

class Phone: Equatable {
    var name: String
    init(name: String) {
        self.name = name
    }
}

Phone(name: "iPhone") == Phone(name: "Zfilp")
// Error : Type 'Phone' does not conform to protocol 'Equatable'
// Do you want to add protocol stubs?

분명히 Equatable을 채택했는데도 불구하고도 에러가 발생합니다.

 

클래스에서는 구조체나 열거형과 다르게 Equatable 메서드를 필수적으로 구현해줘야 합니다.

static func == (lhs: Self, rhs: Self) -> Bool

 

메서드를 정의해 준 뒤 다시 사용해 보겠습니다.

class Phone: Equatable {
    var name: String
    init(name: String) {
        self.name = name
    }
    
    static func == (lhs: Phone, rhs: Phone) -> Bool {
        return lhs.name == rhs.name
    }
}

Phone(name: "iPhone") == Phone(name: "Zfilp")
// false

비교가 잘되는 걸 확인했습니다.

 

 

아 참고로 열거형은 어떤 식으로 비교가 가능한지 살펴보고 마치겠습니다.

enum Phone: Equatable {
    case iPhone
    case zFilp
    case blackBerry
}

Phone.iPhone == Phone.zFilp
// false

이렇게 간단히 비교를 해볼 수 있습니다.

 

구조체열거형에서는 프로토콜 Equatable에 대한 메서드 컴파일러가 자동으로 구현을 해주네요.

 

제 생각에는 Equatable은 완벽하게 동작을 하므로 애플이 편의성을 위해 우리가 자주 사용하는 구조체나 열거형에서는 자동으로 구현되게 만든 것 같네요.

(찾아보니 Swift 4.1에서 업데이트가 됐다고 합니다.)

 

 

부족한 설명이지만, 조금은 이해 가셨나요?

틀린 내용이 있다면 언제든지 지적해 주시면 감사히 받겠습니다. 🫠
읽어주셔서 감사합니다 😃

 

반응형
profile

Danny의 iOS 컨닝페이퍼

@Danny's iOS

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!