Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

تعريف البروتوكولات

جزء من قسم البرمجة كائنية التوجه في رحلة 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اختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: Playground لـ Swift