macOS

[Swift] Protocol(1)

Daesiker 2021. 3. 16. 16:04
반응형

프로토콜이란?

프로토콜은 특정 작업이나 기능에 적합한 메서드, 프로퍼티 및 기타 요구사항을 정의해준다. 그 다음 프로토콜을 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으로 지정이 되기 때문에 컴퓨터마다 값이 다를 수 있다.

 

반응형

'macOS' 카테고리의 다른 글

[Framework] 파인더 커스텀 FIFinderSync(1)  (0) 2021.04.29
[iOS, macOS] PromiseKit  (0) 2021.03.23
[Swift] UserDefaults  (0) 2021.03.15
[iOS, macOS] Alamofire Framework(3)  (2) 2021.03.11
[iOS, macOS] Alamofire Framework(2)  (0) 2021.03.10