지난번에 이어서 프로토콜에 대해 자세히 살펴볼까합니다!
저번 글에서 설명한 Equatable이 동등성 비교(==, != 연산자 사용)를 위해 필요한 프로토콜 이라면
Comparable은 <, <=, >=, > 연산자를 사용하여 대소를 비교하기 위해 필요한 프로토콜인데요!
일단 공부의 시작인 공식문서부터 볼까요
📍공식문서
A type that can be compared using the relational operators <, <=, >=, and >.
protocol Comparable : Equatable
정의를 보면 이 프로토콜을 채택함으로서 <, <=, >=, > 연산자를 쓸 수 있다고 하네요!
근데 Comparable은 Equatable을 채택하고 있네요..?
그렇다... 우린 Comparable을 준수하는 타입을 만들면 자연스레 Equatable도 준수하는 타입을 만들어야하는 것이다!!
Comparable을 준수하면 대소비교, 동등성 비교 모두 가능해진다는 것을 알 수 있어요. 즉, <, <=, >=, > 연산자들은 물론 ==, != 연산자를 모두 쓸 수 있다는 것!!
📍기본타입에서의 Comparable
근데 우리 String, Int, Double 과 같은 타입은 기본적으로 그냥 대소비교 해주고있었잖아요?
print("abcd">"abcde")
print(1>2)
이렇게요. 우린 String 타입이나 Int 타입에 따로 Comparable을 준수하도록 설정해준 적이 없는데 어떻게 이게 가능한가 하면!
Equatable 처럼 기본 자료형은 이미 swift에서 다 알아서 세팅해놓았다는 말씀.
그럼 대충 감이 오는게 커스텀 타입인 구조체, 클래스, 열거형은 대소비교해주려면 뭔가 작업을 해주어야겠죠!
Equatble 처럼 Comparable 준수하도록 만들어줘야합니다.
📍구조체에서의 Comparable
이렇게 그냥 구조체에 대소비교 연산자 쓰면 에러가 납니다.
🚨 Binary operator '>' cannot be applied to two 'Struct' operands
그래서 Comparable 채택해줬는데도 에러가 난다???
🚨 Type 'Struct' does not conform to protocol 'Comparable'
뭐지? 구조체에서 Equatable은 그냥 채택만 해줘도 됐는데..
Equatable과 다르게 Comparable는 구조체도 기본구현 메서드를 구현해줘야합니다!
귀찮아.. Equatable처럼 프로퍼티 값 모두 비교하는 것으로 기본 구현 그냥 해주면안되나? 생각할 수 있지만
Swift에서 개발자에게 어떤 프로퍼티의 값을 비교할건지 정중하게 물어보는 것이라고 생각하고 컴 다운해봅시다. :)
에러알림에서 Fix 버튼 눌러보면 < 메서드 구현하라고 나오는데요!
이처럼 Comparable을 채택한다고 <, <=, >=, > 에 대한 메서드를 다 구현해주는게 아니라, 우리가 < 메서드만 구현해주면 알아서 다른 연산자도 대소비교 가능하도록 해줍니다!!
우리는 < 메서드를 통해 대소비교 연산자를 썼을 때 어떤 프로퍼티들을 비교할건지 기준만 설정해주는 것이죠 ㅎㅎ
struct Struct : Comparable{
static func < (lhs: Struct, rhs: Struct) -> Bool {
return lhs.str<rhs.str && lhs.int<rhs.int //str 과 int 모두 커야 큰 것으로 판별
}
var str : String
var int : Int
var bool : Bool
}
let struct1 = Struct(str: "string", int: 0, bool: true)
let struct2 = Struct(str: "string2", int: 2, bool: true)
print(struct1<struct2) // true
그럼 이렇게 대소비교를 할 수 있게 됩니닷
📍클래스에서의 Comparable
클래스에서도 한번 사용해볼까요.
Comparable 채택해주고 봤더니 이건 또 에러가 2개나 뜨네..’;;
일단 차근차근 Fix 버튼 눌러줘봅시다.
하나는 < 메서드 구현하라고 나오고 ( 이건 뭐 구조체에서도 했으니 예상 했던거!!)
하나는 == 메서드를 구현하라고 나옵니다.. 이건 또 뭔
자 근데 생각해보면 Comparable의 공식문서를 봤을 때 Comparable 자체가 Equatable을 준수하고 있어서 아까 설명할 때 Comparable를 준수하면 자동으로 Equatable를 준수하게 되는거라고 말씀드렸잖아요?
Equatable 글에서 봤을 때 Equatable를 준수하려면 클래스는 == 메서드 구현이 필요하다고 했죠..(참조가 아닌 값을 비교하기 위해 개발자가 직접 구현해서 비교하는 프로퍼티 값을 특정해준다)
어떻게 보면 당연하게 구현해줘야하는거였네요!
class Class : Comparable{
static func < (lhs: Class, rhs: Class) -> Bool {
return lhs.str<rhs.str && lhs.int<rhs.int //str 과 int 모두 커야 큰 것으로 판별
}
static func == (lhs: Class, rhs: Class) -> Bool {
return lhs.str==rhs.str && lhs.int==rhs.int && lhs.bool==rhs.bool
}
var str : String
var int : Int
var bool : Bool
init(str: String, int: Int, bool: Bool) {
self.str = str
self.int = int
self.bool = bool
}
}
let class1 : Class = Class(str: "string", int: 0, bool: true)
let class2 : Class = Class(str: "string2", int: 1, bool: true)
print(class1<class2) //true
print(class1>class2) //false
print(class1==class2) //false
위 코드를 보면 저는 동등성 비교할 때는 str, int, bool 프로퍼티가 모두 같아야 동일하게 본다고 했고
대소비교할 때는 str과 int 두 값이 모두 클 경우에 큰 인스턴라고 판별할것이라는 코드를 작성해주었습니다 :)
📍열거형에서의 Comparable
열거형도 안봐주면 섭하니 간단하게 보면
연관값 없는 열거형은 Comparable 만 채택해줘도 대소비교가 됩니다.
아니 case 끼리 어떻게 대소비교를해.. 한다면 밑으로 가는 case일수록 크다고 인식하더라구요!
enum Enum : Comparable {
case case1
case case2
case case3
}
let enum1 = Enum.case1
let enum2 = Enum.case2
print(enum1 < enum2) // true
연관값이 있어도 딱히 <함수 구현해주는게 아니라 Comparable 만 채택해주면되네요??
enum Enum : Comparable {
case case1(caseNumber : Int)
case case2(caseNumber : Int)
case case3(caseNumber : Int)
}
let enum1 = Enum.case1(caseNumber : 1)
let enum2 = Enum.case1(caseNumber : 2)
let enum3 = Enum.case2(caseNumber : 2)
print(enum1 < enum2) // true
print(enum2 < enum3) // true
'Swift' 카테고리의 다른 글
[Swift] 프로토토콜 뽀개볼까 (4) | Hashable, HashTable (0) | 2024.05.09 |
---|---|
[Swift] 프로토콜 뽀개볼까 (3) | Codable (feat. Encodable & Decodable), JSON이란? (1) | 2024.04.28 |
[Swift] 프로토콜 뽀개볼까 (1) | Equatable & ==, === 차이 (1) | 2024.04.21 |
[Swift] Swift의 동시성 프로그래밍 (3) | async/await (WWDC 2021) (0) | 2024.04.07 |
[Swift] Swift의 동시성 프로그래밍 (2) | Swift Concurrency의 등장 (feat. async-await & Coroutine & Continuation) (0) | 2024.03.24 |