본문 바로가기

iOS/Swift

Swift) Equatable에 대해 알아보자

 

 

안녕하세요 :) 소들입니다

연말 정산 글에 1주일에 글 1개 안쓰면 게임 1주일 접겠다고

뭔 망언을 해놔서..; 게임을 접을 수 없어 글을 쓰는 이 지경입니다 제가

 

어떤 분이 메타 타입에 대해 글을 써달라 하셨는데,

내용이 너무 길어질 것 같아서 그건 다음으로 미루고

처음 접했을 때 어려울 수 있는 프로토콜 몇가지에 대해 정리부터 하려고 합니다!!

Equatable이나 Hashable이나 Comparable이나 등등!!!!

(절대 내용 짧을 거 같아서 그런거 절대 아닐 거임)

 

모든 포스팅은 편의 말투로 합니다~!

 

 

 

 

1. Int, String 끼리는 비교가 되면서 왜 구조체, 클래스 인스턴스끼리는 비교가 안 될까

 

위 말이 뭔말이셈이냐면,

우리가 다음과 같이 아무렇지 않게 사용해오던

 

 

let num1 = 3
let num2 = 3
 
num1 == num2            // true
 
let str1 = "so"
let str2 = "deul"
 
str1 == str2            // false

 

 

== 이 연산자가 바료 비교 연산자란 말임

근데 위처럼 num, str끼리는 == 연산자를 써서 위처럼 비교를 할 수 있고,

원하는 결과(true, false)도 얻을 수 있지만

 

 

struct Human {
    var name = ""
    var age = 0
}
 
let human1 = Human.init()
let human2 = Human.init()
 
human1 == human2     // Binary operator '==' cannot be applied to two 'Human' operands

 

 

우리가 만든 구조체, 클래스 인스턴스를 ==로 비교하려고 하면

위처럼 에러가 뜸

 

그 이유가 무엇이냐면,

Int, Double, String이란 자료형은 가장 기본적인 자료형으로,

Equatable이란 프로토콜이 이미 모두 채택되어 컴파일러가 자동으로 구현해주기 때문임

 

그래서 도대체 Equatable이 뭐냐고?

 

Equatable은 타입끼리 비교(==)연산을 하기 위해선 필수적으로 구현해야 하는 프로토콜!!

 

 

 

 

안에 static func == 이거 보이시져??

타입끼리 ==을 쓰기 위해서 필수적으로 채택해야 하는 게 Equatable이란  프로토콜이구나~!

채택하고 나서 func ==를 구현 해줘야 하는구나~!

정도로 알면 되겠다!!

 

그럼 이제 구조체, 클래스, 열거형에서 Equatable을 사용하는 방법에 대해 알아 보겠음 :)

 

 

 

 

2. 구조체 / 클래스/ 열거형에서 비교 연산을 쓰는 방법

 

2-1. 구조체

 

앞서 말했듯 같은 구조체 인스턴스끼리 비교를 하고 싶다면,

Equatable 프로토콜을 채택하면 됨

 

 

struct Human: Equatable {
    var name = ""
    var age = 0
}
 
let human1 = Human.init()
let human2 = Human.init(name: "", age: 19)
 
human1 == human2        // false

 

 

이렇게 Human 구조체에 Equatable 프로토콜을 채택해주면,

이젠 Human 인스턴스끼리 비교가 가능해짐!!

 

에엥 프로토콜 내에 정의되어 있는 ==이란 메서드에 대해 구현 안 해줬는데요?

라고 할 수 있지만,

열거형 내 모든 타입이 기본 타입(name: String, age: Int)라면,

직접 메서드를 구현해주지 않아도 Equatable을 채택하는 것만으로도 사용 가능

 

참고로 이렇게 할 경우,

해당 구조체 내의 모든 프로퍼티(name, age)가 같아야만 true임

 

만약 나는 이름이 같으면 같은 인스턴스로 취급하고 싶어!! 라고 한다면,

 

 

struct Human: Equatable {
    var name = ""
    var age = 0
    
    static func == (lhs: Self, rhs: Self) -> Bool {
        return lhs.name == rhs.name
    }
}
 
let human1 = Human.init()
let human2 = Human.init(name: "", age: 19)
 
human1 == human2        // true

 

 

이렇게 직접 구현해주면, name에 한해서만 비교를 하기 때문에

human1과 human2의 age란 프로퍼티가 달라도 둘은 동일하다고 비교하게 만들 수도 있음

(근데 웬만해서 특수하진 않은 경우, 걍 기본을 쓰는게..ㅎㅎ)

 

 

 

2-2. 클래스

 

흐헿ㅎ 구조체처럼 Equatable 채택만 하면 자동으로 되겠지 흫헿

 

 

class Human: Equatable {     // Type 'Human' does not conform to protocol 'Equatable'>
    var name = ""
    var age = 0
}        

 

 

응 어림도 없어

클래스의 경우 Equatable을 채택하는 것만으로 자동으로 구현해주지 않음

따라서 직접 == 메서드를 구현해야 함

 

 

class Human {
    var name = ""
    var age = 0
}
 
extension HumanEquatable {
    static func == (lhs: Human, rhs: Human) -> Bool {
        return lhs.name == rhs.name && lhs.age == rhs.age
    }
}
 
let human1 = Human.init()
let human2 = Human.init()
human2.age = 10
 
human1 == human2        // false

 

 

그렇다고 합니다 :D

 

 

 

 

2-3. 열거형

 

1️⃣ 연관값이 없는 열거형

 

연관값이 없는 열거형의 경우,

 

 

enum Gender {
    case male
}
 
let man = Gender.male
let man2 = Gender.male
 
man == man2   // true

 

 

Equatable을 채택하지도 않아도 자동으로 구현이 됨

 

 

2️⃣ 연관값이 있는 열거형

 

연관값이 있는 열거형의 경우,

 

 

enum GenderEquatable {
    case male(name: String)
}
 
let man = Gender.male(name: "so")
let man2 = Gender.male(name: "deul")
 
man == man2   // false

 

 

Equatable을 채택만 해줘도 자동으로 구현이 됨

(채택은 필수, ==메서드 구현은 필수 X)

 

 

 

 

 

 

.

.

.

오늘은 Equatable이란 프로토콜에 대해 알아봤어요!

어렵진 않지만 제대로 모를 땐 헷갈릴 수 있을 것 같아서

확실하게 정리하고 가시길 바라겠습니다 :)

 

오타 및 피드백 대환영

 

 



Calendar
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
최근 댓글
Visits
Today
Yesterday