-
Swift - Comparable ProtocolProgramming/Swift 2022. 1. 15. 23:42
안녕하세요 BeePeach입니다 :>
오늘 공부해볼 내용은 지난 포스팅에 이어서 기본적인 Protocol 중에 하나인 Comparable 프로토콜입니다.
Equatable과 마찬가지로 우리가 기본적인 Type들의 대소비교를 할 수 있던 것은 기본적으로 제공해주는 Type들이 Comparable을 채용하고 있었기 때문입니다.
그럼 같이 한번 공부해보도록 해요!
Adopting a Protocol Using a Synthesized Implementation
Comparable은 Equtable과는 조금 다른 부분이 있습니다.
두 값이 같다 다르다와 어느값이 더 크다 작다는 다른 문제입니다.
무엇을 기준으로 더 크거나 작다는것일까요??
예시를 들어보겠습니다.
A라는 사람은 키가 180cm이고 몸무게가 85kg입니다.
B라는 사람은 키가 175cm이고 몸무게가 100kg입니다.
그럼 A가 B보다 크다고 할 수 있을까요??
이 기준은 '키'에있고 '몸무게'를 기준으로 하면 B가 A보다 더 크게 됩니다.
그래서 그 기준을 정해줘야 합니다.
하지만 A와 B는 다릅니다. 이건 기준이 없더라도 다르다는 것을 알 수 있습니다.
그래서 Swift에서는 Comparable의 synthesized implementation을 다른 protocol보다 제한적으로 제공합니다.
- Enumeration이 rawValue를 가지고 있지 않을 때
- Enumeration이 Comparable protocol을 채용한 associated value만을 가지고 있을 때
기본적으로 Enum에게만 synthesized implementation을 제공합니다.
Enum의 경우도 Comparable protocol을 채용한 associated value를 가지고 있더라도 <을 구현하면 제공하지 않습니다.
그리고 반드시 extension이 아닌 구현에서 추가시켜야힙니다.
Comparable
Comparable 프로토콜을 채용한 Type은 <, > 연산자로 값을 비교할 수 있게 됩니다.
Comparable의 구현을 보면 Equatable 프로토콜을 상속하고 있습니다.
즉 우리가 Comaparable을 채용하기 위해서는 Equtable 프로토콜의 요구사항도 함께 만족시켜줘야 합니다.
그리고 Comparable 프로토콜을 채용한 element로만 이루어진 Sequence와 Collection은 sort(), sorted() 메서드를 사용할 수 있게 됩니다. ( sort(by:), sorted(by:)는 Comparable을 채용하지 않아도 사용 가능합니다. )
그럼 Comparable의 요구사항을 확인해볼까요??
헉.. 4개나 존재하네요??
하지만 다행히 4개를 모두 구현할 필요는 없습니다.
이 중 < 만 구현하고 Equatable의 요구사항인 ==만 구현하면 Swift가 알아서 나머지를 구현해줍니다.
< 대신 >, <=, >= 만 구현하면 요구사항을 만족하지 않았다는 에러 메시지가 출력됩니다.
Class
Class는 synthesized implementation를 제공하지 않기 때문에 우리가 무엇을 기준으로 비교할지 직접 선언해줘야 합니다.
한번 Class를 선언하고 인스턴스를 만들어서 비교해보도록 하겠습니다.
year, month, day를 프로퍼티로 가지는 CustomDate라는 Class를 생성했습니다.
CustomDate는 당연히 Comparable를 채용하지 않았기 때문에 비교를 하려고 하니 에러가 발생하는 것을 확인할 수 있습니다.
Comparable의 필수 요구사항인 < 연산자를 구현했습니다.
여기서 비교의 기준은 모든 프로퍼티를 비교하도록 했습니다.
year를 먼저 비교하고 여기서 나눠지지 않는다면 month, day 순서대로 비교해서 대소를 나타내도록 만들었습니다.
이렇게 모든 프로퍼티를 비교하는 게 제일 좋지만 원한다면 year만 비교하고 끝내도 에러는 발생하지 않습니다.
비교의 기준을 우리가 정해주는 것뿐입니다.
하지만 위에서 설명했듯이 Comparable의 요구사항만을 충족 시키면 안 됩니다.
< 만 구현을 하니까 Equatable의 요구사항을 만족하지 않았다는 에러가 발생하네요.
이번에는 == 연산자까지 구현해서 모든 요구사항을 만족시켰습니다.
그랬더니 이전에 에러가 발생하는 < 비교 부분에서 에러가 사라지고 우리가 원하는 대로 대소 비교를 하는 것을 확인할 수 있습니다.
심지어 우리가 구현하지 않은 >= 연산자를 이용해도 에러가 나지 않습니다.
그리고 이제 CustomDate로 이루어진 Array에서 sort(), sorted() 메서드를 사용할 수 있는 것도 확인 가능합니다.
Comparable을 채용하지 않는다면 sort(by:) 메서드를 이용해서 클로저 파라미터에 비교 기준을 직접 전달해야 하지만 Comparable을 채용한다면 우리가 정의한 기준에 따라 정렬을 해줍니다.
Structure
Struct도 마찬가지로 우리가 모두 구현을 해주어야 합니다.
그런데 잠깐 생각해 볼 게 있습니다.
Equtable 프로토콜은 Struct의 경우 모든 저장 프로퍼티가 Equtable프로토콜을 채용한 Type이라면 synthsized implementation을 제공해줬었습니다.
즉 이 조건을 만족하면 == 연산자의 구현을 제공해준다는 소리입니다.
예제를 보면 Person 구조체는 프로퍼티의 Type이 String, Int로 모두 기본적으로 Equtable을 채용한 Type입니다.
그래서 ==의 구현은 Equtable을 채용하기만 한다면 Swift에서 자동적으로 제공해줍니다.
Comparable은 Equtable을 상속하고 있었죠??? 그래서 심지어 Equtable을 직접 채용할 필요도 없어집니다.
이경우에 우리는 Comparable만 채용하고 < 연산자만 구현하면 비교 연산자를 사용할 수 있게 됩니다.
그래서 이번에는 비교 기준을 age만 비교하도록 구현했습니다.
그래서 이름은 'B'가 'J'보다 작은 값이지만 age로만 비교하기 때문에 비교 결과가 true인 것을 확인할 수 있습니다.
Enumeration
Enum은 유일하게 Comparable의 synthsized Implementation을 제공해주는 CustomType이었습니다.
조건은 Raw Value를 가지고 있지 않을 경우와 Associated value을 가지고 있다면 모든 Type이 Comparable을 채용하고 있을 경우 총 2가지 경우였습니다.
School 열거형에는 초등학교, 중학교, 고등학교, 대학교 4가지 case가 존재합니다.
Raw value가 없으니까 비교가 가능할까요??
Equtable에서 봤던 것처럼 이렇게 한다고 바로 비교 연산자를 제공하지 않습니다.
예제를 보면 에러가 발생하는 것을 알 수 있죠??
Comparable을 직접 채용해줘야 합니다.
Comparable을 채용해주니 비교가 가능한 것을 확인할 수 있습니다.
기준은 case선언 순서인 거 같네요.
먼저 선언된 case 일수록 작은 값을 나타냅니다.
그럼 이제 Associated Value를 적용시켜볼까요??
Extension에서 Comparable을 채용하도록 해봤습니다.
주의할 점은 여기서 School 열거형 구현 코드와 extension이 같은 파일에 존재한다는 것입니다.
공식문서에서 다른 파일에서 extension을 이용해서 채용하지 말라고 설명하고 있습니다.
그리고 < 도 직접 구현하지 말라고 설명하고 있네요.
아무튼 다시 돌아와서 구현한 것을 Comparable만 채용하고 있는데 비교 연산자를 사용할 수 있는 것을 확인할 수 있습니다.
비교 기준은 1순위가 case의 순서 2순위가 associated value에서 정의된 순서인 것으로 확인됩니다.
그럼 마지막으로 RawValue가 추가된 경우를 확인해보겠습니다.
RawValue가 추가되었다면 반드시 < 를 직접 구현해주어야 합니다.
예시를 보면 rawValue값을 기준으로 비교하도록 구현을 해줬습니다.
그래서 case끼리 비교를 하면 rawValue값으로 비교를 하게 됩니다.
RawValue를 이용해서 인스턴스를 생성하는 경우에는 생성되는 인스턴스가 Optional이기 때문에 반드시 Unwrapping을 해줘야 합니다.
여기서는 !를 이용하고 있지만 실제 프로젝트에서는 !의 사용을 자제하는 것을 잊지 마세요!
참고자료
https://developer.apple.com/documentation/swift/comparable
Apple Developer Documentation
developer.apple.com
https://docs.swift.org/swift-book/LanguageGuide/Protocols.html
Protocols — The Swift Programming Language (Swift 5.5)
Protocols A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of tho
docs.swift.org
여러분의 새로운 도전을 응원합니다 | KxCoding
Mastering SwiftUI 더 적은 코드로, 더 멋진 UI 만들기
kxcoding.com
728x90'Programming > Swift' 카테고리의 다른 글
Swift - Generic (0) 2022.01.17 Swift - Hashable Protocol (0) 2022.01.16 Swift - Equatable Protocol (0) 2022.01.14 Swift - Protocol Extension (0) 2022.01.12 Swift - Protocol Optional Requirement (0) 2022.01.04