iOS/Swift

[Swift] Protocol 프로토콜 [2]

최지철 2023. 10. 16. 16:46
728x90
반응형

 

선택적 요구 사항 Optional Requirements

  • @objc -> Objective - C에서도 사용가능하도록 하는 키워드
  • Optional 은 멤버를 선택적 멤버로 변경하게 하는 것이다
  • 프로토콜 키워드 앞에 @objc 추가, 멤버 선언 앞에도 추가해야지 사용가능하며, 멤버 선언 시 optional키워드를 추가해야한다
  • AnyObject를 자동 상속 -> 클래스 전용 프로토콜이 된다
@objc protocol 프로토콜 이름 {
	@objc optional 요구사항들
}

 

프로토콜 확장 Protocol Extension

  • 프로토콜 역시 type이기 때문에, extension으로 확장가능
  • 프로토콜 확장시, 프로토콜을 채용한 모든 type에 추가
  • Extension 사용시, 프로토콜에 구현을 추가 -> 프로토콜을 채용한 type에 사실상 구현을 추가하는 것
  • type에서 구현한 함수가 우선순위가 높다.
protocol Figure {
	func draw()
}

extension Figure {
	func draw() {
    	print("draw figure")
    }
}

 

 

Equatable protocol ==

  • 가장 기본적인 프로토콜, 컴파일러가 자동으로 구현해줌
  • 값의 동일성을 비교할 수 있는 프로토콜
  • == 비교 연산자
  • 구조체 끼리, 비교 하고싶으면 Equatable을 채택만 하면됨
  • 클래스에서 사용하고 싶으면, 직접 구현해야함
  • 열거형의 경우 자동으로 구현 , 채택도 필요X
  • 인스턴스 끼리 정확하게 비교해야함
struct Human: Equatable {
    var name = ""
    var age = 0
    
    static func == (lhs: Self, rhs: Self) -> Bool {
        return lhs.name == rhs.name
    }
}
 
let human1 = Human.init()
let human2 = Human.init(name: "", age: 19)
 
human1 == human2        // true

class Human {
    var name = ""
    var age = 0
}
 
extension Human: Equatable {
    static func == (lhs: Human, rhs: Human) -> Bool {
        return lhs.name == rhs.name && lhs.age == rhs.age
    }
}
 
let human1 = Human.init()
let human2 = Human.init()
human2.age = 10
 
human1 == human2        // false



enum Gender: Equatable {
    case male(name: String)
}
 
let man = Gender.male(name: "so")
let man2 = Gender.male(name: "deul")
 
man == man2   // false

 

Hashable protocol 

  • 딕셔너리 키 타입과 셋 요소 타입이 구현해야 하는 Hashable 프로토콜
  • Hashable 프로토콜을 채택하는 타입은 모두 값을 정수인 해시값으로 표현할 수 있다.
  • Hashable 프로토콜을 채택하는 커스텀 타입의 저장 프로퍼티가 모두 Hashable 프로토콜을 채택하고 있다면, 별다른 구현없이 Hashable 프로토콜을 채택하는 것 만으로 Hashable한 동작을 제공한다.
  • Hashable은 Equatable을 채택
    • 해시 충돌이 발생하는 경우를 알기 위해서는 두 인스턴스가 값이 일치하는 확인해야하기 때문에 Equatable 프로토콜을 채택해야한다
    • 해시 충돌 -> Hash 값을 생성하는 built in 메소드인 hasher(_:) 가 서로 다른 값에 대해 동일한 Hash 값을 생성
  • 클래스의 경우 Hashable 프로토콜을  채택해야 하는 자료형에서 사용할 수 있다.
  • 구조체의 경우 채택만 하면됨
  • 열거형의 경우, 연관값이 있으면 채택, 없으면 자동으로 구현됨
struct Human: Hashable {
    let name: String
    let age: Int
}
 
let myDict: [Human: Int] = [:]      

class Human {
    let name = "Sodeul"
    let age = 28
}
 
extension Human: Hashable {
    static func == (lhs: Human, rhs: Human) -> Bool {
        return lhs.name == rhs.name && lhs.age == rhs.age
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
        hasher.combine(age)
    }
}
 
let myDict: [Human: Int] = [:]

enum Gender: Hashable {
    case male(age: Int)
}
 
let myDict: [Gender: Int] = [:]

Comparable protocol  >, >=, <=, <

  • 값의 크기와 순서를 비교할 때 필요한 Comparable 프로토콜
  • string의 경우, 유니코드를 기준으로 비교
  • Equtable을 채택
  • 구조체의 경우, 채택과 구현까지 해야함
  • 클래스의 경우도 채택과 구현
  • 열거형의 경우도, Swift 5.3 미만의 경우 Comparable을 채택 & 구현
    • 연관값이 있다면 5.3이상의 경우 채택으로만 가능
    • 없다면, 채택, 구현 다해야함
  •  
struct Person: Comparable {
    static func < (lhs: Person, rhs: Person) -> Bool {
        return lhs.age < rhs.age
    }
    
    var name = ""
    var age = 0
}
 
let sodeul = Person.init(name: "sodeul", age: 28)
let clone = Person.init(name: "clone", age: 30)
 
sodeul = clone           // false
sodeul <= clone          // true

 
class Person: Comparable {
    static func == (lhs: Person, rhs: Person) -> Bool {
        return lhs.name == rhs.name && lhs.age == rhs.age
    }
    
    static func < (lhs: Person, rhs: Person) -> Bool {
        return lhs.age < rhs.age
    }
    
    var name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}
 
let sodeul = Person.init(name: "sodeul", age: 28)
let clone = Person.init(name: "clone", age: 30)
 
sodeul > clone           // false
sodeul <= clone          // true


enum Number: Int, Comparable {
    static func < (lhs: Number, rhs: Number) -> Bool {
        return lhs.rawValue < rhs.rawValue
    }
    
    case one, two, three
}
 
Number.one > Number.two     // false
728x90
반응형