🔥 프로토콜의 속성 요구사항

488자
6분

프로토콜은 준수하는 타입에 특정 이름과 타입을 가진 인스턴스 속성이나 타입 속성을 제공하도록 요구할 수 있습니다. 프로토콜은 속성이 저장 속성인지 계산 속성인지는 지정하지 않고, 오직 요구되는 속성의 이름과 타입만을 지정하죠. 또한 각 속성이 읽기 전용(gettable)인지 혹은 읽기-쓰기(gettable and settable) 모두 가능한지도 명시합니다.

만약 프로토콜에서 읽기-쓰기 가능한 속성을 요구한다면, 상수 저장 속성이나 읽기 전용 계산 속성으로는 그 요구사항을 충족시킬 수 없습니다. 반면 프로토콜에서 읽기 전용 속성만을 요구한다면 어떤 종류의 속성으로도 그 요구사항을 만족시킬 수 있죠. 심지어 코드에서 유용하게 사용할 수 있다면 쓰기 가능한 속성으로 구현해도 무방합니다.

프로토콜에서 속성 요구사항은 항상 var 키워드를 앞에 붙여 변수 속성으로 선언됩니다. 읽기-쓰기 속성은 타입 선언 뒤에 { get set }을, 읽기 전용 속성은 { get }을 작성하여 표시합니다.

protocol SomeProtocol {
    var mustBeSettable: Int { get set } // 읽기-쓰기 속성 요구사항
    var doesNotNeedToBeSettable: Int { get } // 읽기 전용 속성 요구사항
}
swift

타입 속성 요구사항을 프로토콜에서 정의할 때는 항상 static 키워드를 앞에 붙여야 합니다. 클래스에서 타입 속성 요구사항을 구현할 때는 classstatic 키워드를 사용할 수 있지만, 프로토콜에서는 static만 사용 가능하답니다.

protocol AnotherProtocol {
    static var someTypeProperty: Int { get set } // 타입 속성 요구사항
}
swift

다음은 단일 인스턴스 속성 요구사항을 가진 프로토콜의 예시입니다.

protocol FullyNamed {
    var fullName: String { get } // 풀 네임을 제공하는 속성 요구사항
}
swift

FullyNamed 프로토콜은 준수하는 타입에 풀 네임(full name)을 제공하도록 요구합니다. 프로토콜은 준수하는 타입의 성질에 대해서는 아무것도 지정하지 않고, 단지 그 타입이 스스로에 대한 풀 네임을 제공할 수 있어야 한다는 것만 명시하죠. 프로토콜은 String 타입의 읽기 전용 인스턴스 속성 fullName을 가져야 한다고 선언합니다.

아래는 FullyNamed 프로토콜을 채택하고 준수하는 간단한 구조체의 예시입니다.

struct Person: FullyNamed {
    var fullName: String // FullyNamed 프로토콜 요구사항 충족
}
 
let john = Person(fullName: "John Appleseed")
// john.fullName은 "John Appleseed"
swift

이 예제는 특정 이름을 가진 사람을 나타내는 Person이라는 구조체를 정의합니다. 정의부 첫 줄에서 FullyNamed 프로토콜을 채택한다고 명시하죠.

Person의 각 인스턴스는 String 타입의 fullName이라는 단일 저장 속성을 가지고 있습니다. 이는 FullyNamed 프로토콜의 단일 요구사항과 일치하며, Person이 프로토콜을 올바르게 준수함을 의미합니다. (만약 프로토콜 요구사항이 충족되지 않으면 Swift는 컴파일 시점에 에러를 발생시킵니다.)

다음은 FullyNamed 프로토콜을 채택하고 준수하는 좀 더 복잡한 클래스의 예시입니다.

class Starship: FullyNamed {
    var prefix: String? // 선택적인 접두어 저장 속성
    var name: String // 필수적인 이름 저장 속성
 
    init(name: String, prefix: String? = nil) {
        self.name = name
        self.prefix = prefix
    }
 
    var fullName: String { // FullyNamed 프로토콜 요구사항 충족
        return (prefix != nil ? prefix! + " " : "") + name
    }
}
 
var ncc1701 = Starship(name: "Enterprise", prefix: "USS")
// ncc1701.fullName은 "USS Enterprise"
swift

이 클래스는 우주선을 위한 읽기 전용 계산 속성으로 fullName 속성 요구사항을 구현합니다. 각 Starship 클래스 인스턴스는 필수적인 name과 선택적인 prefix를 저장하죠. fullName 속성은 prefix 값이 존재하면 그 값을 사용하고, name 앞에 붙여 우주선의 풀 네임을 만듭니다.

이렇게 프로토콜의 속성 요구사항을 통해 준수하는 타입이 특정 속성을 제공하도록 강제할 수 있습니다. 이는 프로토콜에 기반한 코드를 작성할 때 매우 유용하게 사용될 수 있죠. 프로토콜과 속성의 조합으로 더욱 유연하고 추상화된 코드를 작성해 보세요!

lecture image