Menu
Coddy logo textTech

Definiowanie protokołów

Część sekcji Programowanie obiektowe ścieżki Swift w Coddy. Lekcja 27 z 57.

Protokół określa wymagania (metody i właściwości), nie implementując ich. Typ spełnia wymagania protokołu, udostępniając wszystkie wymagane elementy. Można go wtedy używać wszędzie tam, gdzie wymagany jest ten protokół:

protocol Describable {
    func describe() -> String
}

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

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

Wynik:

Book: Dune

W przeciwieństwie do dziedziczenia protokół działa zarówno dla struktur, klas, jak i wyliczeń, a typ może być zgodny z wieloma protokołami. Protokół określa tylko, co typ może robić; każdy typ decyduje, jak:

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())

Wynik:

(1, 2)
high

Wymagania dotyczące właściwości określają typ oraz to, czy właściwość jest tylko do odczytu ({ get }), czy można ją również zapisywać ({ get set }). Wymaganie { get } może spełniać właściwość przechowywana lub obliczana:

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)

Wynik:

ada
Planet 3

Jeśli typ deklaruje zgodność, ale nie spełnia któregoś z wymagań, kod się nie kompiluje. Kompilator sprawdza każdą zgodność, więc kod korzystający z protokołu może na niej polegać:

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

// struct Ticket: Priced { var price = 10 }
// błąd: typ 'Ticket' nie jest zgodny z protokołem 'Priced'
challenge icon

Wyzwanie

Łatwy

Zadeklaruj protokół Shape z właściwością tylko do odczytu name (String) i metodą area() zwracającą Double. Spraw, by struktury Rectangle (width, height) i Circle (radius, używając 3.0 jako π, aby uprościć obliczenia) były z nim zgodne, i nadaj im nazwy rectangle i circle.

Dostarczony kod odczytuje wiersze r,3,4 lub c,2, tworzy odpowiedni kształt i wypisuje rectangle: 12.0.

Twój kod umieść w plikach Shape.swift, Rectangle.swift i Circle.swift. Plik main.swift zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.

Spróbuj swoich sił

// Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
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 iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Edytor online Swift