0411(목) 프로토콜 - hwj0623/ios_swift GitHub Wiki

Reference

야곰의 블로그 Swift Protocol 이해하기 #1 Swift에서 프로토콜 중심 프로그래밍(POP)하기

프로토콜 정의

  • 인스턴스끼리 서로 정보를 주고 받기 위해 합의한 규약, 명세 등을 의미한다.

프로토콜의 특징

  • 특정 역할을 수행하기 위한 메서드, 프로퍼티, 이니셜라이저 등의 요구사항을 정의한다.

    • 메서드는 선언만 하고, 함수를 구현하지는 않는다.
    • 프로퍼티도 선언만 한다.
      • 대신 readable 한 내용은 get, writable도 가능한 프로퍼티는 set으로 지정한다.
  • 특정 구조체, 클래스, 열거형에 대해 특정 기능 등을 구현할 것을 강요하는 것

  • 구조체, 클래스, 열거형은 프로토콜을 채택(Adopted)해서 프로토콜의 요구사항을 실제로 구현할 수 있습니다.

  • 어떤 프로토콜의 요구사항을 모두 따르는 타입은 그 ‘프로토콜을 준수한다(Conform)’고 표현합니다.

  • 프로토콜의 요구사항을 충족시키려면 프로토콜이 제시하는 기능을 모두 구현해야 합니다.

Basic Example (1)

/// 프로토콜 : '~할 수 있는'의 형식으로 네이밍한다.
protocol SecretaryQualifiable {
    func manageSchedule ()             // 함수를 구현하지는 않는다.
    func brewCoffee()
    func drive()
    
    var certification: String { get }  // get - readable property
    var drivingLicense: String { get }
}

/// 프로토콜 SecretaryQualifiable를 채택한 구조체 Secretary
struct Secretary: SecretaryQualifiable {
    func manageSchedule() {
        print("Managing schedule well done!")
    }
    func brewCoffee() {
        print("I drip a any cup of coffee")
    }
    func drive() {
        print("drive anywhere")
    }
    
    var certification: String
    var drivingLicense: String
}

/// Assistant는 SecretaryQualifiable 프로토콜을 "채택"했다
struct Assistant: SecretaryQualifiable {
    func manageSchedule() {
        print("Managing schedule so so!")
    }
    
    func brewCoffee() {
        print("I drip only cold brew coffee")
    }
    
    func drive() {
        print("drive in highway")
    }
    
    var certification: String
    var drivingLicense: String
}

struct CEO {
    var secretary: SecretaryQualifiable     // 프로토콜에 부합하는 자는 모두 secretary가 될 수 있다.
}
/// 프로토콜을 "conform(준수)" 한 구조체 선언 및 초기화
let secretary1: Secretary = Secretary(certification: "KoreaUniv_Bachelor", drivingLicense: "2종 자동")
let secretary2: Assistant = Assistant(certification: "KoreaUniv_Master", drivingLicense: "1종 자동")

/// Secretary와 Assistant 모두 SecretaryQualifiable을 따르므로 아래의 코드는 이상없이 컴파일된다.
var master: CEO = CEO(secretary: secretary1)
master.secretary = secretary2

Basic Example (2)

  • 프로토콜은 다른 프로토콜을 상속받을 수 있다.
  • 프로토콜의 프로퍼티가 겹치는 경우, Type이 다르다면 구조체 등에서 프로퍼티 충돌이 일어난다.
  • 상속받은 프로토콜의 프로퍼티명과 중복되지 않도록 한다.
protocol Drivable{
    var drivingLicense: Int { get }
    func drive()
}
protocol Brewable {
    func brewCoffee()
}
/// Drivable, Brewable 을 "상속"받은 프로토콜
protocol SecretaryQualifiable: Drivable, Brewable { 
    func manageSchedule ()     
    func brewCoffee()
    func drive()

    var certification: String { get }

    // 해당 프로퍼티가 상속받은 프로퍼티 (Int형 drivingLicense)와 충돌한다. 
    var drivingLicense: String { get }   
}

Basic Example (3)

  • 아래와 같이 비서의 조건이 Drivable과 Brewable이라면, 이를 상속한 SecretaryQualifiable 를 구현하는 것으로도 구조체가 비서가 될 수 있다.
import UIKit


/// 프로토콜의 프로퍼티가 겹치는 경우는 구조체 등에서 프로퍼티 충돌이 일어난다.
protocol Drivable{
    func drive()
    var drivingLicense: String { get }
}
/// 프로토콜
protocol Brewable {
    func brewCoffee()
}

/// 프로토콜 : '~할 수 있는'의 형식으로 네이밍
protocol SecretaryQualifiable: Drivable, Brewable { // Drivable, Brewable 을 "상속"받은 프로토콜
    func manageSchedule ()      // 함수를 구현하지 않는다.
    /// get - readable property
    var certification: String { get }
}

struct Secretary: SecretaryQualifiable{  /// Secretary는 Drivable, Brewable 프로토콜을 "adopt"했다
    func manageSchedule() {
        print("Mananging schedule welldone!")
    }
    func brewCoffee() {
        print("I drip a any cup of coffee")
    }
    func drive() {
        print("drive anywhere")
    }
    
    var certification: String
    var drivingLicense: String
}

/// Secretary는 SecretaryQualifiable 프로토콜을 "채택"했다
struct Assistant: SecretaryQualifiable {
    func manageSchedule() {
        print("Mananging schedule so so!")
    }
    
    func brewCoffee() {
        print("I drip only cold brew coffe")
    }
    
    func drive() {
        print("drive in highway")
    }
    
    var certification: String
    var drivingLicense: String
}

struct CEO {
    var secretary: Drivable&Brewable
}

/// 프로토콜을 "conform(준수)" 한 구조체 선언 및 초기화
let secretary1: Secretary = Secretary(certification: "KoreaUniv_Bachelor", drivingLicense: "2종 자동")
let secretary2: Assistant = Assistant(certification: "KoreaUniv_Master", drivingLicense: "1종 자동")

var master: CEO = CEO(secretary: secretary1)
master.secretary = secretary2