[Swift] 프로토콜 (Protocol)

김형근·2024년 7월 23일

[Swift] 문법

목록 보기
17/20

🍎 [Swift] 프로토콜 (Protocol)

  • 프로토콜은 특정 역할을 수행하기 위한 메서드, 프로퍼티, 이니셜라이저 등의 요구사항을 정의합니다.
  • 구조체, 클래스, 열거형은 프로토콜을 채택(Adopt)해서 프로토콜의 요구사항을 구현할 수 있습니다.

어떤 프로토콜의 요구사항을 모두 따르는 타입은 그 '프로토콜을 준수한다(Confirm)' 고 표현 합니다.
프로토콜의 요구사항을 충족시키려면 프로토콜이 제시하는 기능을 모두 구현해야 합니다.


🍏 프로토콜 정의 문법

  • 프로토콜은 특정 역할을 수행하기 위해 필요한 메서드, 프로퍼티, 이니셜라이저 등을 정의합니다. 프로토콜 자체는 구현을 포함하지 않으며, 이를 채택한 타입이 실제 구현을 제공합니다.
protocol 프로토콜 이름 {
    /* 정의부 */
}

🧃 예시: Talkable 프로토콜 정의

protocol Talkable {
    
    // 프로퍼티 요구
    // 프로퍼티 요구는 항상 var 키워드를 사용합니다.
    // get은 읽기만 가능해도 상관 없다는 뜻이며
    // get과 set을 모두 명시하면 읽기 쓰기 모두 가능한 프로퍼티여야 합니다.
    var topic: String { get set }
    var language: String { get }
    
    // 메서드 요구
    func talk()
    
    // 이니셜라이저 요구
    init(topic: String, language: String)
}

🍏 프로토콜 채택 및 준수

  • 구조체, 클래스 또는 열거형이 프로토콜을 채택하려면 해당 타입에 프로토콜 요구사항을 모두 구현해야 합니다.

🧃 예시: Person 구조체가 Talkable 프로토콜 채택 및 준수

struct Person: Talkable {
    var topic: String
    let language: String
    
    // talk 메서드를 구현하여 Talkable 프로토콜의 요구사항을 준수합니다.
    func talk() {
        print("\(topic)에 대해 \(language)로 말합니다.")
    }
    
    // 프로토콜의 이니셜라이저 요구사항을 구현합니다.
    init(topic: String, language: String) {
        self.topic = topic
        self.language = language
    }
}

Person 구조체는 Talkable 프로토콜의 모든 요구사항을 준수하여 구현.


🍏 프로토콜 상속

  • 프로토콜은 다른 프로토콜을 상속받을 수 있으며, 다중 상속이 가능합니다.
    이는 하나의 타입이 여러 프로토콜의 요구사항을 동시에 준수해야 할 때 유용합니다.
protocol Readable {
    func read()
}

protocol Writeable {
    func write()
}

protocol ReadSpeakable: Readable {
    // func read() // Readable 프로토콜의 요구사항을 상속받습니다.
    func speak()
}

protocol ReadWriteSpeakable: Readable, Writeable {
    // func read() // Readable 프로토콜의 요구사항을 상속받습니다.
    // func write() // Writeable 프로토콜의 요구사항을 상속받습니다.
    func speak()
}

🧃 예시: SomeType이 여러 프로토콜을 채택 및 준수

struct SomeType: ReadWriteSpeakable {
    // Readable 프로토콜의 요구사항을 구현합니다.
    func read() {
        print("Read")
    }
    
    // Writeable 프로토콜의 요구사항을 구현합니다.
    func write() {
        print("Write")
    }
    
    // ReadWriteSpeakable 프로토콜의 요구사항을 구현합니다.
    func speak() {
        print("Speak")
    }
}

SomeType은 Readable, Writeable, ReadWriteSpeakable 프로토콜의 모든 요구사항을 구현.


🍏 클래스 상속과 프로토콜

  • 클래스가 상속과 프로토콜 채택을 동시에 하려면, 상속받으려는 클래스를 먼저 명시하고 그 뒤에 채택할 프로토콜 목록을 작성합니다.

🧃 예시: 클래스 상속과 프로토콜 채택

class SuperClass: Readable {
    // Readable 프로토콜의 요구사항을 구현합니다.
    func read() {
        print("read")
    }
}

class SubClass: SuperClass, Writeable, ReadSpeakable {
    // Writeable 프로토콜의 요구사항을 구현합니다.
    func write() {
        print("write")
    }
    
    // ReadSpeakable 프로토콜의 요구사항을 구현합니다.
    func speak() {
        print("speak")
    }
}

SubClass는 SuperClass를 상속받고, Writeable 및 ReadSpeakable 프로토콜을 채택합니다.


🍏 프로토콜 준수 확인

  • 인스턴스가 특정 프로토콜을 준수하는지 확인할 수 있습니다.
  • is, as 연산자를 사용합니다.

🧃 예시: 프로토콜 준수 확인

let sup: SuperClass = SuperClass() // SuperClass 인스턴스를 생성
let sub: SubClass = SubClass() // SubClass 인스턴스를 생성

var someAny: Any = sup
someAny is Readable // true - someAny는 SuperClass 인스턴스로, SuperClass는 Readable 프로토콜을 준수

someAny is ReadSpeakable // false - someAny는 SuperClass 인스턴스로, SuperClass는 ReadSpeakable 프로토콜을 준수하지 않음

someAny = sub
someAny is Readable // true - someAny는 SubClass 인스턴스로, SubClass는 SuperClass를 상속받아 Readable 프로토콜을 준수
someAny is ReadSpeakable // true - someAny는 SubClass 인스턴스로, SubClass는 ReadSpeakable 프로토콜을 준수

someAny = sup

// 프로토콜 준수 여부 확인 후 안전하게 타입 캐스팅
if let someReadable: Readable = someAny as? Readable {
    someReadable.read() // someAny가 Readable 프로토콜을 준수하면 read 메서드 호출
} // 출력: "read"

if let someReadSpeakable: ReadSpeakable = someAny as? ReadSpeakable {
    someReadSpeakable.speak() // someAny가 ReadSpeakable 프로토콜을 준수하면 speak 메서드 호출
} // 동작하지 않음 - someAny는 SuperClass 인스턴스로, ReadSpeakable 프로토콜을 준수하지 않음

someAny = sub

if let someReadable: Readable = someAny as? Readable {
    someReadable.read() // someAny가 Readable 프로토콜을 준수하면 read 메서드 호출
} // 출력: "read"

프로토콜 준수 확인을 통해 인스턴스가 특정 프로토콜을 준수하는지 체크하고, 타입 캐스팅을 통해 안전하게 프로토콜 메서드를 호출할 수 있습니다.

profile
꾸준히 기록하기

0개의 댓글