Menu
Coddy logo textTech

프로토콜 정의하기

Coddy Swift 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 57개 중 27번째.

프로토콜은 구현 없이 요구 사항(메서드와 속성)을 나열합니다. 타입은 모든 요구 사항을 제공함으로써 프로토콜을 준수하며, 그러면 프로토콜이 예상되는 어디에서든 사용할 수 있습니다:

protocol Describable {
    func describe() -> String
}

struct Book: Describable {
    let title: String
    func describe() -> String { "Book: \(title)" }
}

print(Book(title: "Dune").describe())

출력:

Book: Dune

상속과 달리 프로토콜은 구조체, 클래스, 열거형 모두에서 동일하게 작동하며, 하나의 타입은 여러 프로토콜을 따를 수 있습니다. 프로토콜은 타입이 무엇을 할 수 있는지만 말하고, 각각의 타입이 어떻게 할지는 스스로 결정합니다:

protocol Describable {
    func describe() -> String
}

struct Point: Describable {
    var x = 0, y = 0
    func describe() -> String { "(\(x), \(y))" }
}

enum Level: Describable {
    case low, high
    func describe() -> String { self == .low ? "low" : "high" }
}

print(Point(x: 1, y: 2).describe())
print(Level.high.describe())

출력:

(1, 2)
high

프로퍼티 요구사항은 프로퍼티의 타입과 해당 프로퍼티가 읽기 전용({ get })인지, 또는 쓰기도 가능한지({ get set })를 지정합니다. { get } 요구사항은 저장 프로퍼티나 계산 프로퍼티로 충족할 수 있습니다.

protocol Named {
    var name: String { get }
}

struct User: Named {
    let name: String
}

struct Planet: Named {
    var number: Int
    var name: String { "Planet \(number)" }
}

print(User(name: "ada").name)
print(Planet(number: 3).name)

출력:

ada
Planet 3

어떤 타입이 준수한다고 선언했지만 요구 사항을 충족하지 못하면 컴파일되지 않습니다. 컴파일러는 모든 준수 여부를 확인하므로, 프로토콜을 사용하는 코드는 이를 신뢰할 수 있습니다:

protocol Priced {
    var price: Int { get }
    func discounted(by percent: Int) -> Int
}

// struct Ticket: Priced { var price = 10 }
// error: 타입 'Ticket'이 프로토콜 'Priced'를 준수하지 않습니다
challenge icon

챌린지

쉬움

읽기 전용 속성 name(String)과 Double을 반환하는 메서드 area()를 포함하는 프로토콜 Shape을 선언하세요. 구조체 Rectangle(width, height)과 Circle(radius, 숫자를 간단하게 유지하기 위해 π에 3.0 사용)이 이를 준수하도록 만들고, 이름을 각각 rectangle과 circle로 지정하세요.

제공된 코드는 r,3,4 또는 c,2 형식의 줄을 읽고, 일치하는 도형을 생성한 다음 rectangle: 12.0을 출력합니다.

코드는 Shape.swift, Rectangle.swift, Circle.swift에 작성하세요. main.swift에는 제공된 입력/출력 코드가 있으며 편집할 수 없습니다.

직접 해보기

// 제공된 입력/출력 코드: 그대로 유지하세요
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
    let p = line.split(separator: ",").map(String.init)
    if p[0] == "r" {
        let s = Rectangle(width: Double(p[1])!, height: Double(p[2])!)
        print("\(s.name): \(s.area())")
    } else {
        let s = Circle(radius: Double(p[1])!)
        print("\(s.name): \(s.area())")
    }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: Swift 플레이그라운드