프로토콜이란?
프로토콜은 특정 작업이나 기능에 적합한 메서드, 프로퍼티 및 기타 요구사항을 정의해준다. 그 다음 프로토콜을 Class, Struct, Enum에서 채택하여 이런 요구사항을 실제로 구현할 수 있도록 도와준다. 프로토콜은 메서드, 프로퍼티 등을 정의만 하고, 이 프토토콜을 채택한 곳에서 구현을 한다. object-c 언어의 .h 파일과 .m 파일과 같은 느낌이다. 직접 만들수도 있고 이미 만들어져 있는 프로토콜을 채택하기도 한다. 오늘은 가장 많이 사용하는 프로토콜 들을 알아볼려고 한다.
Equtable
Equtable은 말 그대로 같은지 아닌지를 비교할 수 있도록 도와주는 프토토콜이다. 이 프로토콜을 채용하면 객체와 객체, 혹은 같은 구조체로 만들어진 요소들을 비교할 수 있게 된다. ==을 통해 같은지를 비교할 수 있고 !=을 통해 같지 않은지를 비교할 수 있다.
class StreetAddress {
let number: String
let street: String
let unit: String?
init(_ number: String, _ street: String, unit: String? = nil) {
self.number = number
self.street = street
self.unit = unit
}
}
extension StreetAddress: Equatable {
static func == (lhs: StreetAddress, rhs: StreetAddress) -> Bool {
return
lhs.number == rhs.number &&
lhs.street == rhs.street &&
lhs.unit == rhs.unit
}
}
extension 키워드를 통해 Equtable 프로토콜을 채택하였다. Equtable 프로토콜은 static func == (Self, Self) -> Bool 함수를 필수로 사용해야한다. 안 그러면 에러가 발생한다. 저 함수를 통해 클래스 안에 있는 어떤 상수랑 비교할 것인지 반환해준다. 해당 예제에서는 number, street, unit 3개가 모두 같을 때만 true를 반환한다.
Result
let addresses = [StreetAddress("1490", "Grove Street"),
StreetAddress("2119", "Maple Avenue"),
StreetAddress("1490", "Grove Street")]
let home = StreetAddress("1400", "16th Street")
print(addresses[0] == home) //false
print(addresses[0] == addresses[2]) //true
첫번째는 name은 같지만 street 값이 달라서 false를 반환하였고 두번째는 둘다 같아서 true를 반환했다.
Comparable
Equtable이랑 비슷한 프로토콜로 객체나 구조체를 연산자를 통해 비교가 가능하게 도와주는 프로토콜이다. <, >, <=, >= 등의 연산을 수행할 수 있도록 도와준다.
struct Date {
let year: Int
let month: Int
let day: Int
}
extension Date: Comparable {
static func < (lhs: Date, rhs: Date) -> Bool {
if lhs.year != rhs.year {
return lhs.year < rhs.year
} else if lhs.month != rhs.month {
return lhs.month < rhs.month
} else {
return lhs.day < rhs.day
}
}
}
해당 예제는 Date라는 년, 월, 일이 있는 구조체를 선언하고 extension 키워드를 통해 Comparable 프로토콜을 채택해서 년 → 월 → 일 순으로 비교하여 앞에 값과 뒤의 값을 비교하여 Bool을 리턴하는 함수를 생성하였다.
Result
let spaceOddity = Date(year: 1969, month: 7, day: 11) // July 11, 1969
let moonLanding = Date(year: 1969, month: 7, day: 20) // July 20, 1969
if moonLanding > spaceOddity {
print("Major Tom stepped through the door first.")
} else {
print("David Bowie was following in Neil Armstrong's footsteps.")
}
// Prints "Major Tom stepped through the door first."
Date 구조체로 된 상수 spaceOddity와 moonLanding을 선언하고 비교를 한 결과 moonLanding의 day의 값이 spaceOddity의 day값보다 크기 때문에 true를 반환하여 "Major Tom stepped through the door first."가 출력되었다.
Hashable
정수 해쉬 값을 제공하는 타입이다. 이 프로토콜을 채택을 하면 해당 객체를 Set 또는 Dictionary의 key로 사용이 가능하다. 정수 hash값이 있어야 set과 dictionary의 value값을 찾을 때의 속도가 훨씬 빨라지기 때문에 swift는 hash값이 있어야만 set과 dictionary의 key로 사용할 수 있게 만들었다. hash값은 임의의 값으로 값이 다를 수 있다.
struct GridPoint: Hashable {
var x: Int
var y: Int
}
let nextTap = GridPoint(x: 0, y: 1)
print(nextTap.x.hashValue)
print(nextTap.y.hashValue)
print(nextTap.hashValue)
Hashable만 채택을 하면 별다른 함수 없이 hashValue를 호출할 수 있다. 각각의 hashValue는 값이 같을 수 없으며 이 값은 random으로 지정이 되기 때문에 컴퓨터마다 값이 다를 수 있다.
Uploaded by Notion2Tistory v1.1.0