TIL: 프로토콜 상속

Royce·2025년 3월 29일

Swift 문법

목록 보기
50/63

프로토콜 상속

  • Swift의 프로토콜은 다중 상속이 가능하다
  • 즉, 프로토콜이 다른 여러 프로토콜을 상속받아 요구 사항들을 모두 포함할 수 있다

프로토콜 정의 및 상속하기

protocol Device {
    func powerOn()
    func powerOff()
}

protocol Adjustable {
    func increaseLevel()
    func decreaseLevel()
}

protocol AdvancedDevice: Device, Adjustable {   // 다중 상속 사용
    func resetSettings()
}
  • AdvancedDeviceDeviceAdjustable을 상속받는다
  • 프로토콜 상속 시, 상속받은 모든 요구 사항들을 포함하게 된다

프로토콜을 채택 및 구현하기 (클래스 예제)

class SmartLight: AdvancedDevice {
    func powerOn() {
        print("스마트 전등 켜짐")
    }
    
    func powerOff() {
        print("스마트 전등 꺼짐")
    }
    
    func increaseLevel() {
        print("밝기 증가")
    }
    
    func decreaseLevel() {
        print("밝기 감소")
    }
    
    func resetSettings() {
        print("설정 초기화됨")
    }
}

let myLight = SmartLight()
myLight.powerOn()          // 출력: 스마트 전등 켜짐
myLight.increaseLevel()     // 출력: 밝기 증가
myLight.resetSettings()     // 출력: 설정 초기화됨
  • SmartLight 클래스는 AdvancedDevice 프로토콜을 채택하여 모든 요구 사항을 구현하고 있다
  • 다중 상속을 사용하여 다양한 기능을 통합할 수 있다

클래스 전용 프로토콜 (AnyObject)

  • Swift에서 프로토콜을 클래스 전용으로 제한할 수 있다
  • 구조체와 열거형은 해당 프로토콜을 채택할 수 없다
protocol DataManager: AnyObject {   // 클래스 전용 프로토콜
    func saveData()
    func loadData()
}
  • DataManagerAnyObject를 상속받아 클래스 전용 프로토콜이 된다
  • 구조체나 열거형은 채택할 수 없다

클래스에서의 구현 예제

class FileManager: DataManager {
    func saveData() {
        print("파일 데이터 저장")
    }
    
    func loadData() {
        print("파일 데이터 불러오기")
    }
}

let myFileManager = FileManager()
myFileManager.saveData()   // 출력: 파일 데이터 저장
myFileManager.loadData()    // 출력: 파일 데이터 불러오기
  • FileManager 클래스는 DataManager 프로토콜을 준수하고 있다
  • 구조체로 구현하려 하면 에러가 발생한다

프로토콜 합성 (Protocol Composition)

  • Swift에서 & 연산자를 사용하여 여러 프로토콜을 동시에 요구하는 임시 타입을 정의할 수 있다

프로토콜 정의하기

protocol Identifiable {
    var id: String { get }
}

protocol Printable {
    func printInfo()
}
  • Identifiable은 식별자를 요구하며, Printable은 정보를 출력하는 기능을 요구한다

구조체에서의 프로토콜 채택 예제

struct User: Identifiable, Printable {
    var id: String
    var name: String
    
    func printInfo() {
        print("사용자 ID: \(id), 이름: \(name)")
    }
}

let user = User(id: "12345", name: "Royce")
user.printInfo()   // 출력: 사용자 ID: 12345, 이름: Royce
  • User 구조체는 IdentifiablePrintable 프로토콜을 모두 준수한다

프로토콜 합성 문법 사용하기 (&)

func showDetails(of entity: Identifiable & Printable) {
    entity.printInfo()
}

showDetails(of: user)  // 출력: 사용자 ID: 12345, 이름: Royce
  • 함수의 매개변수 타입을 Identifiable & Printable 로 선언하면 두 프로토콜을 모두 준수하는 객체만 전달할 수 있다

프로토콜 합성을 사용한 타입 정의 예제

let printableEntity: Identifiable & Printable = user
printableEntity.printInfo()   // 출력: 사용자 ID: 12345, 이름: Royce
  • printableEntity는 두 프로토콜의 요구 사항만 사용 가능하다

프로토콜 타입으로 저장 시의 주의점

  • 프로토콜 타입으로 저장할 경우, 프로토콜에서 선언된 메서드나 속성만 접근할 수 있다
let printableThing: Printable = user
printableThing.printInfo()     // 출력: 사용자 ID: 12345, 이름: Royce

// print(printableThing.id)    // 에러 발생 - Printable에는 'id' 정의가 없음

요약

  • 프로토콜은 다중 상속이 가능하며, 상속받은 모든 프로토콜의 요구 사항을 구현해야 한다.
  • AnyObject를 사용하여 클래스 전용 프로토콜을 정의할 수 있다.
  • 프로토콜 합성(&)을 사용하여 여러 프로토콜을 동시에 요구하는 임시 타입을 만들 수 있다.
  • 프로토콜 타입으로 저장하면 해당 프로토콜에서 선언된 메서드나 속성만 접근할 수 있다.
profile
iOS 개발자 지망생

0개의 댓글