Swift/문법

프로토콜(protocol)

khon98 2021. 1. 30. 12:11

프로토콜

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

- 구조체, 클래스, 열거형은 프로토콜을 채택해서 프로토콜의 요구사항을 실제로 구현할 수 있음

- 어떤 프로토콜의 요구사항을 모두 따르는 타입은 '프로토콜을 준수한다'라고 표현함

- 프로토콜의 요구사항을 충족시키려면 프로토콜이 제시하는 기능을 모두 구현해야 함

 

protocol 프로토콜 이름 {

정의부

}

 

 

프로토콜 상속

- 프로토콜은 클래스와 다르게 다중 상속이 가능함

 

protocol 프로토콜 이름 : 부모 프로토콜 이름 목록 {

정의부

}

 

 

클래스 상속과 프로토콜

- 클래스에서 상속과 프로토콜 채택을 동시에 하려면 상속받으려는 클래스를 먼저 명시하고 그 뒤에 채택할 프로토콜 목록을 작성함

 

 

프로토콜 준수 확인

- 인스턴스가 특정 프로토콜을 준수하는지 확인할 수 있음

- is, as 연산자 사용

 

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 // 읽기 전용, 상수 / var로 바꿔도 상관 없음
    
    // 메서드 구현
    func talk() {
        print("\(topic)에 대해 \(language)로 말합니다")
    }
    
    // 이니셜라이저 구현
    init(topic: String, language: String) {
        self.topic = topic
        self.language = language
    }
}


protocol Readable {
    func read()
}

protocol Writealbe {
    func write
}

protocol ReadSpeakable: Readable {
    func speak()
}

protocol ReadWriteSpeakable: Readable, Writeable {
    func speak()
}

struct Sometype: ReadWriteSpeakable {
    func read() {
        print("Read")
    }
    
    func write() {
        print("Write")
    }
    
    func speak() {
        print("Speak")
    }
}

// 클래스 상속과 프로토콜
class SuperClass: Readable {
    func read() { print("read") }
}

class SubClass: SuperClass, Writeable, ReadSpeakable {
    func write() { print("write") }
    func speak() { print("speak") }
}

// 프로토콜 준수 확인
let sup: SuperClass = SuperClass()
let sub: SubClass = SubClass()

var someAny: Any = sup
someAny is Readable // true
someAny is ReadSpeakable // true

someAny = sub
someAny is Readable // true
someAny is ReadSpeakable // true

someAny = sup

if let someReadable: Readable = someAny as? Readable {
    someReadable.read()
} // read

if let someReadSpeakable: ReadSpeakable = someAny as? ReadSpeakable {
    someReadSpeakable.speak()
} // 동작하지 않음

if let someReadable: Readable = someAny as? Readable {
    someReadable.read()
} // read