Menu
Coddy logo textTech

הגדרת פרוטוקולים

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Swift של Coddy. שיעור 27 מתוך 57.

פרוטוקול מונה דרישות (מתודות ומאפיינים) בלי לממש אותן. טיפוס מציית לפרוטוקול על ידי אספקת כל הדרישות, ואז אפשר להשתמש בו בכל מקום שבו מצופה הפרוטוקול:

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 }
// שגיאה: הטיפוס 'Ticket' אינו תואם לפרוטוקול 'Priced'
challenge icon

אתגר

קל

הצהירו על פרוטוקול Shape עם מאפיין לקריאה בלבד name (String) ושיטה area() שמחזירה Double. צרו את המבנים Rectangle (רוחב, גובה) ו-Circle (רדיוס, תוך שימוש ב-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 אונליין