본문으로 바로가기

본문에서 클래스라고 하곤 있지만 구조체에서도 똑같이 적용됨

프로토콜의 확장

- 프로토콜을 채택한 타입에서 실제 메서드를 구현할때 똑같은 코드를 반복해야하는 불편함을 제거

- 단순히 기본구현을 제공하는 개념

- 프로토콜의 확장에서 기본구현을 할시 클래스에서 구현을 안해도 기본구현된 내용으로 동작

- 단, 클래스에서 구현을 할시 클래스에서 구현한 내용이 동작

- 즉, 우선순위가 클래스에서 구현한것이 높고 확장에서 구현한것이 낮다

protocol Remote { // 본체에선 요구사항 정의만 가능
    func turnOn()
    func turnOff()
}

extension Remote { // 확장에서
    func turnOn() {
        print("켜짐")
    }
    
    func turnOff() {
        print("꺼짐")
    }
}

class TVRemote: Remote {
    // 프로토콜의 확장에서 기본구현을 할시
    // 채택한 타입에서 구현을 안해줘도 됨
    // 그럴경우 프로토콜의 확장에서 기본구현한 동작으로 실행됨
    func turnOn() {     // 클래스에서 구현
        print("tv켜짐")
    }
}


let tvRemote: TVRemote = TVRemote()
tvRemote.turnOn()   // 클래스에서 구현한 동작
/*
 콘솔: tv켜짐
 */
tvRemote.turnOff()  // 프로토콜의 확장에서 구현한 동작
/*
 콘솔: 꺼짐
 */

- 프로토콜의 본체에서 요구사항 정의는 안했지만 확장에서 구현한경우

   - 클래스에서 구현을 안할시 프로토콜에서 기본구현한 동작

protocol Remote {
    func turnOn()
    func turnOff()
}

extension Remote {
    func turnOn() {
        print("켜짐")
    }
    
    func turnOff() {
        print("꺼짐")
    }
    
    // 요구사항 정의는 안했지만 확장에서 기본구현 한경우
    func volumUp() {
        print("볼륨업")
    }
}

class TVRemote: Remote {
    
}


let tvRemote: TVRemote = TVRemote()
tvRemote.volumUp()
/*
 콘솔: 볼륨업
 */

   - 클래스에서 구현한경우

      - 인스턴스의 타입이 해당 클래스인경우

      - 클래스에서 구현된 메서드 실행

protocol Remote { // 본체에선 요구사항 정의만 가능
    func turnOn()
    func turnOff()
}

extension Remote { // 확장에서
    func turnOn() {
        print("켜짐")
    }
    
    func turnOff() {
        print("꺼짐")
    }
    
    func volumUp() {
        print("볼륨업")
    }
}

class TVRemote: Remote {
    func volumUp() {
        print("tv 볼륨업")
    }
}


let tvRemote: TVRemote = TVRemote() // 타입이 클래스
tvRemote.volumUp()
/*
 콘솔: tv 볼륨업
 */

      - 인스턴스의 타입이 채택된 프로토콜 타입인 경우

      - 프로토콜의 확장에서 기본구현된 메서드 실행

protocol Remote { // 본체에선 요구사항 정의만 가능
    func turnOn()
    func turnOff()
}

extension Remote { // 확장에서
    func turnOn() {
        print("켜짐")
    }
    
    func turnOff() {
        print("꺼짐")
    }
    
    func volumUp() {
        print("볼륨업")
    }
}

class TVRemote: Remote {
    func volumUp() {
        print("tv 볼륨업")
    }
}


let tvRemote: Remote = TVRemote() // 타입이 프로토콜
tvRemote.volumUp()
/*
 콘솔: 볼륨업
 */