[Swift 기초] 프로토콜

2022. 4. 5. 18:31Swift 기초 정리

728x90

//공부 기록용 포스팅입니다. 틀린 부분이 있을 경우 댓글로 알려주시면 감사합니다! 😎

 

 

1. 프로토콜

protocol 프로토콜이름 {
    /*코드 구현*/
}
타입 타입이름: 프로토콜 채택{
	/*코드 구현*/
}
  • 프로토콜(protocol): 프로그램 구성 요소, 프로토콜에는 그것을 사용하는 클래스에 반드시 있어야 하는 특정 속성과 메서드를 정의한다.
    • 구조체, 클래스, 열거형 등의 어떤 타입에 이러한 기능이 꼭 필요하다고 강요하는 것!
    • 특정 객체가 갖추어야 할 기능이나 속성(메서드, 프로퍼티, 기타 요구사항)에 대한 설계도, 구현해야 할 내용의 명세서
  • 채택(Adopted): 구조체, 클래스, 열거형은 프로토콜을 채택해서 특정기능을 수행하기 위한 프로토콜의 요구사항을 실제로 구현
  • 준수(Conform): 어떤 프로토콜의 요구사항을 모두 따르는 타입을 그 프로토콜을 준수한다고 표현
  • 타입에서 프로토콜의 요구사항을 모두 충족시키려면 프로토콜이 제시하는 청사진의 기능을 모두 구현해야한다.
  • 프로토콜은 기능을 정의하고 제시할 뿐이지 스스로 기능을 구현 X
protocol SampleProtocol{
	func desc(name: String)
}

//SampleProtocol에 접근가능한 이니셜라이저가 없기 때문에 구성할 수 없습니다.
//var sample: SampleProtocol = SampleProtocol()
  • C++의 추상 클래스: 객체를 생성하는 용도가 아니라 상속을 통해 물려받은 클래스가 반드시 가져야 할 프로퍼티와 메서드를 정의하는 용도
  • 자바의 인터페이스: 인터페이스를 implement 한 클래스가 반드시 구현해야 할 메서드를 가지고 있다.

1-1. protocol

protocol Talkable {
    //프로퍼티, 메서드, 이니셜라이저 등을 요구할 수 있다.
    //어떤 특정타입이 해당 프로토콜을 채택했을 떄 프로퍼티와 메서드, 이니셜라이저 등을 구현해야 한다. - 프로토콜에서는 직접 구현 X
    
    //프로퍼티 요구 - 프로퍼티가 읽기만 되느냐, 읽기 쓰기만 되느냐를 표현
    //프로퍼티 요구는 항상 var 키워드를 사용
    var topic: String { get set }
    var language: String { get }
    
    //메서드 요구
    func talk()
    
    //이니셜라이저 요구
    init(topic: String, language: String)
}
  • 프로퍼티, 메서드, 이니셜라이저 등을 요구할 수 있다.
  • 프로토콜에서 직접 구현하는 것이 아니라 어떤 특정 타입이 해당 프로토콜을 채택했을 때 해당 타입에서 프로토콜의 청사진을 모두 직접 구현해야 한다. (실행블록을 작성 X)
  • 프로퍼티 요구는 항상 var 키워드를 사용

1-2. 프로토콜 채택 및 준수

//Person 구조체는 Talkable 프로토콜을 채택
struct Person: Talkable {
    //var: 읽기 쓰기 모두가능
    //let: 읽기 전용으로 동작
    //프로토콜에서 모든 프로퍼티가 {get set}을 요구하면 let을 사용하면 안 된다.
    var topic: String
    let language: String
    
    //읽기 전용 프로퍼티 요구는 연산 프로퍼티로 대체 가능
    //var language2: String { get {return "영어"}}
    
    //읽기, 쓰기 프로퍼티도 연산 프로퍼티로 대체할 수 있다.
    //var subject: String = ""
    //var topic: String {
    //    set{
    //        self.subject = newValue
    //    }
    //    get{
    //        return self.subject
    //}
    //}
    
    
    func talk(){
        print("\\(topic)에 대해 \\(language)로 말해봅시다.")
    }
    
    init(topic: String, language: String){
        self.topic = topic
        self.language = language
    }
}
  • Person 구조체는 Talkable 프로토콜을 채택했다 == Person 구조체는 Talkable 프로토콜이 요구하는 기능들을 직접 구현해야 한다.
    • Person 클래스를 Talkable의 서브 클래스로 정의하는 것 X, Talkable 프로토콜을 구현하는 Person 클래스를 생성하는 것
  • 매개변수 타입뿐만 아니라 반드시 매개변수명까지 일치해야 한다.
  • 읽기, 쓰기 전용 프로퍼티(저장프로퍼티) 요구는 연산 프로퍼티로 대체할 수 있다.

1-3. 프로토콜 상속

protocol 프로토콜 이름: 부모 프로토콜 이름 목록 {
	/* 코드 구현 */
}
  • 프로토콜은 클래스와 다르게 다중 상속이 가능하다.
protocol Readable {
    func read()
}
protocol Writeable {
    func write()
}
protocol ReadSpeakable: Readable {
    //생략해도 똑같이 요구
    //func read()
    func speak()
}
protocol ReadWriteSpeakable: Readable, Writeable {
    //생략해도 똑같이 요구
    //func read()
    //func write()
    func speak()
}
struct SomeType: ReadWriteSpeakable {
    //프로토콜을 채택하고 모두 준수해야한다
    //하나라도 빠지면 Protocol requires func다 ion 'read()' with type'() -> ()'; do you want to add a stub?
    func read() {
        print("Read")
    }
    func write() {
        print("Write")
    }
    func speak() {
        print("Speak")
    }
}

1-4. 클래스 상속과 프로토콜

class 클래스 이름: 상속받으려는 클래스, 채택할 프로토콜 목록 {
	/* 코드 작성 */
}
  • 클래스에서 상속과 프로토콜 채택을 동시에 하려면 상속받으려는 클래스를 먼저 명시하고 그 뒤에 채택할 프로토콜 목록을 작성
class  SuperClass: Readable {
    func read(){
        print("read")
    }
}

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

1-5. 프로토콜 준수 확인

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

1-5-1. is

let sup: SuperClass = SuperClass()
let sub: SubClass = SubClass()

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

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

1-5-2. as

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

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

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

if let someReadSpeakable: ReadSpeakable = someAny as? ReadSpeakable {
    someReadSpeakable.speak()  //speak
}

 

 

 

참고하였습니다. 감사합니다.

https://yagom.net/courses/swift-basic/lessons/타입-확장/topic/프로토콜/

 

스위프트 기초 - 야곰닷넷

스위프트는 문법표현의 다양성이 매우 높은 언어입니다. 그래서 스위프트 문법의 모든 형태를 알기는 꽤 오랜 시간이 걸립니다. 그렇지만 최소한의 핵심 문법을 통해 무리없이 스위프트 문법을

yagom.net

https://www.inflearn.com/course/창원대학교-박동규-교수의-swift-기초-강좌/lecture/1903?tab=note&mm=null 

 

학습 페이지

 

www.inflearn.com

23.06.27 수정) Swift 쉽게, 더 쉽게

https://www.yes24.com/Product/Goods/17652267

728x90