-
Swift - Equatable ProtocolProgramming/Swift 2022. 1. 14. 18:17
안녕하세요 BeePeach입니다 :)
오늘 공부해볼 내용은 기초적인 Protocol 중 하나인 Equatable 프로토콜입니다.
우리가 비교 연산자를 통해서 Int, String 등 기본적인 Type을 서로 비교할 수 있던 것은 Swift Standard library에서 제공하는 대부분의 Type들은 기본적으로 Equatable 프로토콜을 채용하고 있기 때문입니다.
그럼 우리가 직접 만든 Custom Type들은 선언할 때 Equtable을 추가해주지 않는데 비교가 가능할까요??
우리가 주로 만드는 Type은 Class, Struct, Enum이 있을 텐데 어떻게 되는지 하나하나 알아보도록 하겠습니다.
Adopting a Protocol Using a Synthesized Implementation
Apple문서에는 위에 대한 답이 적혀있습니다
Swift에서는 많은 경우에 자동적으로 Equatable, Comparable, Hashable의 conformance를 제공할 수 있습니다.
이를 Synthesized(통합, 조합) implementation이라고 말하고 있습니다.
그리고 Equatable의 synthesized implementation은 다음과 같은 경우에 제공됩니다.
- Structure가 Equatable 프로토콜을 채용하는 stored property만을 가지고 있을 때
- Enumeration이 associated value을 가지고 있지 않을 때
- Enumeration이 Equtable protocol을 채용한 associated value만을 가지고 있을 때
정리해보자면 Struct와 Enum은 프로퍼티나, 케이스가 존재하지만 그것들이 Equatable을 채용하는 멤버일 경우에만 자동으로 적용이 된다는 말입니다.
Class이거나 나머지 경우라면 직접 요구사항을 만족해줘야 합니다.
Equatable
요구사항을 확인하기 전에 먼저 Equtable 프로토콜이 뭔지 정확히 알고 가야겠죠??
Equatable 프로토콜을 채용한 Type들은 ==, !=으로 값을 비교할 수 있습니다.
그리고 Equatable 프로토콜을 채용한 element로 이루어진 collection, sequence는 contain 메서드를 이용할 수 있습니다.
우리가 Array에서 유용하게 사용하는 contain() 메서드는 ==을 이용한다는 것을 짐작할 수 있겠네요.
또한 Equtable 프로토콜은 Comparable, Hashable 프로토콜의 base protocol입니다.
Compare(비교)하거나 hashable을 생각해보면 두 값의 비교로부터 시작하죠?? 값이 같은지 틀린 지를 알아야 위 두 가지 기능도 사용 가능합니다.
그래서 위 두 프로토콜은 Equatable을 상속하고 있습니다.
그리고 헷갈리면 안 되는 게 ==(equal)과 ===(Identical)은 다른 것입니다.
Company라는 class를 하나 선언했습니다.
Class는 Equtable이 자동적으로 구현되지 않는다고 했죠??
그래서 인스턴스 생성 후 == 를 이용하여 비교하면 에러가 나는 것을 확인할 수 있습니다.
하지만 === 은 에러가 나지 않고 false가 나오는 것을 확인할 수 있습니다.
Equtable과 ===(identical)은 관계가 없다는 것을 알 수 있습니다.
그럼 ==을 사용할 수 있도록 Equatable을 채용하려면 필수 요구사항을 구현해주면 되겠죠??
확인해보니 우리가 사용하던 == 연산자만 구현해주면 된다고 합니다.
== 을 구현한다면 !=은 자동으로 구현됩니다.
그럼 class, struct, enum에서 구현을 해보도록 하겠습니다.
Class
방금 선언했던 Company 클래스가 Equatable을 채용하도록 해보겠습니다.
코드의 가독성이 좋아지도록 extension으로 빼서 구현했습니다.
== 연산자를 정의하는 것은 Custom 연산자를 추가하듯이 구현하면 됩니다.
여기서는 name 프로퍼티를 비교해서 name이 같다면 같은 값으로 판단하도록 구현했습니다.
그리고 위에서 설명했던 것처럼 이제 contains() 메서드를 사용할 수 있습니다
헷갈리면 안 되는 부분은 contains(where:) 메서드는 Equtable 프로토콜을 채용하지 않아도 사용할 수 있다는 점입니다.
그 이유는 클로저 파라미터로 비교 여부를 직접 전달하고 있기 때문입니다.
Structure
위 설명에서 Struct는 stored property가 모두 Equatable을 채용하고 있다면 구현할 필요가 없다고 설명하고 있습니다.
그럼 한번 확인해 볼까요??
엥?? 설명과는 다르게 에러가 발생하는 것을 확인할 수 있습니다.
분명 name과 age 프로퍼티는 String, Int로 Equtable를 채용하고 있는 Type인데 뭐가 문제일까요??
구현을 할 필요가 없다고 했지 채용을 하지 말라고는 안 했습니다..
Equtable 프로토콜을 채용만 해주면 ==을 구현할 필요 없이 자동적으로 conformance 됩니다.
Equtable를 추가해주니 에러가 사라지고 비교가 가능한 것을 확인할 수 있습니다.
만약 Equatable을 기본적으로 채용하고 있지 않은 Type이 있다면 Class에서 구현한 것처럼 직접 구현을 해줘야 합니다.
Enumeration
Enum에서는 associated value가 없다면 자동적으로 채용이 된다고 나와있습니다.
한번 확인해볼까요??
Associated value없이 enum에서 ==를 사용해보니 에러가 없이 잘 비교가 되는 것을 확인할 수 있습니다.
심지어 Equtable을 채용하지 않아도 자동으로 제공해주네요!
그럼 RawValue가 있어도 똑같을까요??
RawValue가 있어도 Equtable 채용 없이 비교가 가능한 것을 확인할 수 있습니다.
그럼 Associated value을 적용시킨 예를 보도록 하겠습니다.
Associated value을 적용시키면 struct와 같이 Equatable을 채용해줘야 합니다.
그래도 ==을 직접 구현하지 않아도 되니까 많이 편해졌습니다.
그럼 만약 Equatable을 채용하지 않은 Type이 들어가면 어떻게 되는지 보도록 하겠습니다.
변한 것은 taxi의 associate value의 Type이 String에서 Company로 변경됐다는 것입니다.
하지만 에러 메시지가 발생하는 것을 확인할 수 있습니다.
이럴 때는 Company를 아까 우리가 만든 것처럼 Equtable을 채용하도록 변경해주면 됩니다.
extension을 이용해서 Equtable을 채용하도록 구현해주니 에러가 말끔히 사라진 것을 확인할 수 있습니다.
이렇게 내가 만든 CustomType에서 contain() 메서드를 이용해야 하거나 ==나 !=를 이용해야 한다면 Equtable 프로토콜을 채용하도록 해주면 됩니다.
참고자료
Apple 공식문서
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
https://developer.apple.com/documentation/swift/equatable
Apple Developer Documentation
developer.apple.com
KxCoding Swift 강의
여러분의 새로운 도전을 응원합니다 | KxCoding
Mastering SwiftUI 더 적은 코드로, 더 멋진 UI 만들기
kxcoding.com
728x90'Programming > Swift' 카테고리의 다른 글
Swift - Hashable Protocol (0) 2022.01.16 Swift - Comparable Protocol (0) 2022.01.15 Swift - Protocol Extension (0) 2022.01.12 Swift - Protocol Optional Requirement (0) 2022.01.04 Swift - Protocol Composition (0) 2022.01.03